Prepull for pod & Asym Jobs
This commit is contained in:
@@ -3,10 +3,6 @@ package conf
|
|||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
MongoURL string
|
|
||||||
Database string
|
|
||||||
LokiURL string
|
|
||||||
NatsURL string
|
|
||||||
ExecutionID string
|
ExecutionID string
|
||||||
PeerID string
|
PeerID string
|
||||||
Timeout int
|
Timeout int
|
||||||
@@ -18,7 +14,7 @@ type Config struct {
|
|||||||
KubeCA string
|
KubeCA string
|
||||||
KubeCert string
|
KubeCert string
|
||||||
KubeData string
|
KubeData string
|
||||||
ArgoHost string // when executed in a container will replace addresses with "localhost" in their url
|
ArgoHost string // when executed in a container will replace addresses with "localhost" in their url
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance *Config
|
var instance *Config
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"oc-catalog": "https://oc-catalog:8087"
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"oc-catalog": "https://localhost:8087"
|
|
||||||
}
|
|
||||||
11
go.mod
11
go.mod
@@ -3,10 +3,9 @@ module oc-monitord
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312104524-e28b79ac0d62
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320151407-88d2e526283b
|
||||||
github.com/akamensky/argparse v1.4.0
|
github.com/akamensky/argparse v1.4.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/goraz/onion v0.1.3
|
|
||||||
github.com/nwtgck/go-fakelish v0.1.3
|
github.com/nwtgck/go-fakelish v0.1.3
|
||||||
github.com/rs/zerolog v1.34.0
|
github.com/rs/zerolog v1.34.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
@@ -17,6 +16,7 @@ require (
|
|||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
github.com/goraz/onion v0.1.3 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
github.com/libp2p/go-libp2p/core v0.43.0-rc2 // indirect
|
github.com/libp2p/go-libp2p/core v0.43.0-rc2 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
@@ -49,8 +49,6 @@ require (
|
|||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/snappy v1.0.0 // indirect
|
github.com/golang/snappy v1.0.0 // indirect
|
||||||
github.com/google/gnostic-models v0.7.0 // indirect
|
github.com/google/gnostic-models v0.7.0 // indirect
|
||||||
github.com/google/go-cmp v0.7.0 // indirect
|
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
|
||||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
@@ -64,15 +62,13 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/nats-io/nats.go v1.44.0 // indirect
|
github.com/nats-io/nats.go v1.44.0
|
||||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
|
||||||
github.com/prometheus/client_golang v1.23.0 // indirect
|
github.com/prometheus/client_golang v1.23.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.65.0 // indirect
|
github.com/prometheus/common v0.65.0 // indirect
|
||||||
github.com/prometheus/procfs v0.17.0 // indirect
|
github.com/prometheus/procfs v0.17.0 // indirect
|
||||||
github.com/robfig/cron v1.2.0 // indirect
|
|
||||||
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
|
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
@@ -99,6 +95,5 @@ require (
|
|||||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
|
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
|
||||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
|
|
||||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
213
go.sum
213
go.sum
@@ -1,48 +1,18 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250604083300-387785b40cb0 h1:iEm/Rf9I0OSCcncuFy61YOSZ3jdRlhJ/oLD97Pc2pCQ=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260319065647-5b7edb53a984 h1:6HAlL367LM75T7IokS5H4y7iZg8mrk05uAy/yANKwdc=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250604083300-387785b40cb0/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260319065647-5b7edb53a984/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250620085001-583ca2fbacd5 h1:FEBwueVOOWKYf0tJuE0EKNIbjxmTyCMgkT4qATYsfbo=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260319071818-28b5b7d39ffe h1:CHiWQAX7j/bMfbytCWGL2mUgSWYoDY4+bFQbCHEfypk=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250620085001-583ca2fbacd5/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260319071818-28b5b7d39ffe/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27 h1:iogk6pV3gybzQDBXMI6Qd/jvSA1h+3oRE+vLl1MRjew=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320093030-a62fbc6c7a03 h1:GyfeEHGlyQIFtuzmwsJZ9b64dr9D7zvi6RCo1e/E5wc=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250704084459-443546027b27/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320093030-a62fbc6c7a03/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250715125819-e735f78e58c6 h1:Gnkv59Ntl2RebC5tNauXuxyRXLfZ2XAJ0+ujMyFte5U=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320103359-c34b8c67038b h1:VdLBRXb0wSsR9lzkoEGvhScRe4cNJy/QoGTkyG302uQ=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250715125819-e735f78e58c6/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320103359-c34b8c67038b/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250805113921-40a61387b9f1 h1:53KzZ+1JqRY6J7EVzQpNBmLzNuxb8oHNW3UgqxkYABo=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320151407-88d2e526283b h1:QEdy0FxwWcXYHVLcC06tRmhFl6T/pr2M7l2Auni/sSU=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250805113921-40a61387b9f1/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260320151407-88d2e526283b/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250808140536-e7a71188a3b5 h1:bmEG0M99WXWCHsMNUgfYqQNEM0YyN4dXxYV1LCY5EYg=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250808140536-e7a71188a3b5/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250808141553-f4b0cf5683de h1:s47eEnWRCjBMOxbec5ROHztuwu0Zo7MuXgqWizgkiXU=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250808141553-f4b0cf5683de/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260113155325-5cdfc28d2f51 h1:jlSEprNaUBe628uP9a9TrJ16Q5Ej6OxHlAKNtrHrN2o=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260113155325-5cdfc28d2f51/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260114125749-fa5b7543332d h1:6oGSN4Fb+H7LNVbUEN7vaDtWBHZTdd2Y1BkBdZ7MLXE=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260114125749-fa5b7543332d/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260129122033-186ba3e689c7 h1:NRFGRqN+j5g3DrtXMYN5T5XSYICG+OU2DisjBdID3j8=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260129122033-186ba3e689c7/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260203074447-30e6c9a6183c h1:c19lIseiUk5Hp+06EowfEbMWH1pK8AC/hvQ4ryWgJtY=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260203074447-30e6c9a6183c/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260203083753-4f28b9b589d6 h1:N+0xkioACl3PNo+MquCIIOL/kSICevg340IYOFGQeOw=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260203083753-4f28b9b589d6/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260203150531-ef916fe2d995 h1:ZDRvnzTTNHgMm5hYmseHdEPqQ6rn/4v+P9f/JIxPaNw=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260203150531-ef916fe2d995/go.mod h1:T0UCxRd8w+qCVVC0NEyDiWIGC5ADwEbQ7hFcvftd4Ks=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260212123952-403913d8cf13 h1:DNIPQ7C+7wjbj5RUx29wLxuIe/wiSOcuUMlLRIv6Fvs=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260212123952-403913d8cf13/go.mod h1:jmyBwmsac/4V7XPL347qawF60JsBCDmNAMfn/ySXKYo=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224093610-a9ebad78f3a8 h1:xoC5PAz1469QxrNm8rrsq5+BtwshEt+L2Nhf90MrqrM=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224093610-a9ebad78f3a8/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224120019-0f6aa1fe7881 h1:1JUGErc+3Runda7iapS5sieH+yFqWrGp+ljv7Kly+hc=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224120019-0f6aa1fe7881/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224122900-d18b031a293a h1:gdr886O31Ai5pEFgJC/mrJMJdhplnQg+UJdZF9mV1n4=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224122900-d18b031a293a/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224130821-ce8ef70516f7 h1:p9uJjMY+QkE4neA+xRmIRtAm9us94EKZqgajDdLOd0Y=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260224130821-ce8ef70516f7/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312082544-d7a8f2adaa5c h1:kBb0dpxyInd4Gs1rriz8mkeKwSCOyomn2ZzWY7YWZqc=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312082544-d7a8f2adaa5c/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312083310-f5e199132416 h1:QHR5pzCI/HUawu8pst5Ggio6WPCUUf8XYjNMVk8kSqo=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312083310-f5e199132416/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312104524-e28b79ac0d62 h1:sHzacZxPIKHyjL4EkgG/c7MI8gM1xmLdhaoUx2ZsH+M=
|
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260312104524-e28b79ac0d62/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
|
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc=
|
github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc=
|
||||||
github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
@@ -71,12 +41,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/davecgh/go-spew v1.1.1/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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
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/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=
|
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
|
||||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
@@ -85,15 +55,11 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/etcd-io/etcd v3.3.17+incompatible/go.mod h1:cdZ77EstHBwVtD6iTgzgvogwcjo9m4iOqoijouPJ4bs=
|
github.com/etcd-io/etcd v3.3.17+incompatible/go.mod h1:cdZ77EstHBwVtD6iTgzgvogwcjo9m4iOqoijouPJ4bs=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
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/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
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-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||||
@@ -108,8 +74,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
|||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
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-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
|
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
|
||||||
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
github.com/go-playground/validator/v10 v10.27.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 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
@@ -126,20 +90,15 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
|||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
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 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v1.0.0/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/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||||
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
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 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
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/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||||
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.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@@ -154,6 +113,8 @@ github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
|
|||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
|
||||||
|
github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
@@ -165,6 +126,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
|||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
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 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -173,6 +136,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
|
|||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
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 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||||
github.com/libp2p/go-libp2p/core v0.43.0-rc2 h1:1X1aDJNWhMfodJ/ynbaGLkgnC8f+hfBIqQDrzxFZOqI=
|
github.com/libp2p/go-libp2p/core v0.43.0-rc2 h1:1X1aDJNWhMfodJ/ynbaGLkgnC8f+hfBIqQDrzxFZOqI=
|
||||||
github.com/libp2p/go-libp2p/core v0.43.0-rc2/go.mod h1:NYeJ9lvyBv9nbDk2IuGb8gFKEOkIv/W5YRIy1pAJB2Q=
|
github.com/libp2p/go-libp2p/core v0.43.0-rc2/go.mod h1:NYeJ9lvyBv9nbDk2IuGb8gFKEOkIv/W5YRIy1pAJB2Q=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
@@ -186,6 +151,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||||
|
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
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 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
@@ -195,16 +162,29 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
||||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||||
|
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||||
|
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
|
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
|
||||||
|
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
|
||||||
|
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||||
|
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.0 h1:oGWEVKioVQcdIOBlYM8BH1rZDWOGJSqr9/BKl6zQ4qc=
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
||||||
|
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||||
|
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||||
|
github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo=
|
||||||
|
github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo=
|
||||||
|
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||||
|
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||||
|
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
|
||||||
|
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
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/nats.go v1.44.0 h1:ECKVrDLdh/kDPV1g0gAQ+2+m2KprqZK5O/eJAyAnH2M=
|
github.com/nats-io/nats.go v1.44.0 h1:ECKVrDLdh/kDPV1g0gAQ+2+m2KprqZK5O/eJAyAnH2M=
|
||||||
github.com/nats-io/nats.go v1.44.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
github.com/nats-io/nats.go v1.44.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||||
@@ -215,37 +195,28 @@ github.com/nwtgck/go-fakelish v0.1.3 h1:bA8/xa9hQmzppexIhBvdmztcd/PJ4SPuAUTBdMKZ
|
|||||||
github.com/nwtgck/go-fakelish v0.1.3/go.mod h1:2HC44/OwVWwOa/g3+P2jUM3FEHQ0ya4gyCSU19PPd3Y=
|
github.com/nwtgck/go-fakelish v0.1.3/go.mod h1:2HC44/OwVWwOa/g3+P2jUM3FEHQ0ya4gyCSU19PPd3Y=
|
||||||
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
|
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
|
||||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
|
||||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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.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 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
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_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
||||||
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
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/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
|
|
||||||
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
|
||||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
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/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/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
|
||||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||||
@@ -260,20 +231,24 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
|
|||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||||
@@ -292,10 +267,10 @@ 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.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
|
|
||||||
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
|
||||||
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
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=
|
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
@@ -306,23 +281,19 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
|
||||||
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.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
|
||||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
|
||||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4=
|
||||||
|
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||||
|
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -335,14 +306,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
|
|||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
|
||||||
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/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
|
||||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
|
||||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
|
||||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
|
||||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -356,12 +319,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
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.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -379,40 +336,18 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.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.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.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.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.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
|
||||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
|
||||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
|
||||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
|
||||||
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
|
||||||
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/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
|
||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
|
||||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
|
||||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
|
||||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||||
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/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -425,8 +360,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
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.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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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-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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -449,17 +384,11 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
|
google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
|
||||||
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||||
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.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
|
||||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
|
||||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
|
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
@@ -473,39 +402,25 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
|
|
||||||
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
|
|
||||||
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
|
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
|
||||||
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
|
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
|
||||||
k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
|
|
||||||
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
|
||||||
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
|
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
|
||||||
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
|
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
|
||||||
k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
|
|
||||||
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
|
|
||||||
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
|
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
|
||||||
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
|
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
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=
|
|
||||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
|
|
||||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
||||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
|
||||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
|
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
|
||||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
|
||||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
|
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
|
||||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
|
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
|
||||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
|
||||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
|
||||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
|
||||||
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
||||||
|
octools "cloud.o-forge.io/core/oc-lib/tools"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ func NewArgoLogs(name string, namespace string, stepMax int) *ArgoLogs {
|
|||||||
return &ArgoLogs{
|
return &ArgoLogs{
|
||||||
Name: "oc-monitor-" + name,
|
Name: "oc-monitor-" + name,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
CreatedDate: time.Now().Format("2006-01-02 15:04:05"),
|
CreatedDate: time.Now().UTC().Format("2006-01-02 15:04:05"),
|
||||||
StepCount: 0,
|
StepCount: 0,
|
||||||
StepMax: stepMax,
|
StepMax: stepMax,
|
||||||
stop: false,
|
stop: false,
|
||||||
@@ -109,7 +109,17 @@ func NewArgoPodLog(name string, step string, msg string) ArgoPodLog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogKubernetesArgo(wfName string, execID string, namespace string, watcher watch.Interface) {
|
// LogKubernetesArgo watches an Argo workflow and emits NATS lifecycle events.
|
||||||
|
// It no longer writes directly to the database — all state transitions are
|
||||||
|
// delegated to oc-scheduler (WorkflowExecution) and oc-datacenter (Bookings)
|
||||||
|
// via the dedicated NATS channels.
|
||||||
|
//
|
||||||
|
// - wfName : Argo workflow name (also the name of the root DAG node)
|
||||||
|
// - execID : WorkflowExecution UUID (for oc-scheduler to update state)
|
||||||
|
// - executionsID: run-group ID shared by all bookings of this run
|
||||||
|
// - namespace : Kubernetes namespace
|
||||||
|
// - watcher : Argo watch stream
|
||||||
|
func LogKubernetesArgo(wfName string, execID string, executionsID string, namespace string, watcher watch.Interface) {
|
||||||
var argoWatcher *ArgoWatch
|
var argoWatcher *ArgoWatch
|
||||||
var pods []string
|
var pods []string
|
||||||
var node wfv1.NodeStatus
|
var node wfv1.NodeStatus
|
||||||
@@ -119,6 +129,17 @@ func LogKubernetesArgo(wfName string, execID string, namespace string, watcher w
|
|||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
// nodePhases tracks the last known phase of each step node so we can detect
|
||||||
|
// phase transitions and emit WORKFLOW_STEP_DONE_EVENT exactly once per step.
|
||||||
|
nodePhases := map[string]wfv1.NodePhase{}
|
||||||
|
|
||||||
|
// stepResults captures the final NodeStatus of every completed step so the
|
||||||
|
// WORKFLOW_DONE_EVENT can include a full recap (Steps slice) for oc-scheduler
|
||||||
|
// and oc-catalog to catch up if they missed individual STEP_DONE events.
|
||||||
|
stepResults := map[string]wfv1.NodeStatus{}
|
||||||
|
|
||||||
|
workflowStartedEmitted := false
|
||||||
|
|
||||||
for event := range watcher.ResultChan() {
|
for event := range watcher.ResultChan() {
|
||||||
wf, ok := event.Object.(*wfv1.Workflow)
|
wf, ok := event.Object.(*wfv1.Workflow)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -126,10 +147,22 @@ func LogKubernetesArgo(wfName string, execID string, namespace string, watcher w
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(wf.Status.Nodes) == 0 {
|
if len(wf.Status.Nodes) == 0 {
|
||||||
wfl.Info().Msg("No node status yet") // The first output of the channel doesn't contain Nodes so we skip it
|
wfl.Info().Msg("No node status yet")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Emit WORKFLOW_STARTED_EVENT once ────────────────────────────────
|
||||||
|
if !workflowStartedEmitted {
|
||||||
|
realStart := wf.Status.StartedAt.Time
|
||||||
|
emitLifecycleEvent(octools.WORKFLOW_STARTED_EVENT, octools.WorkflowLifecycleEvent{
|
||||||
|
ExecutionID: execID,
|
||||||
|
ExecutionsID: executionsID,
|
||||||
|
State: enum.STARTED.EnumIndex(),
|
||||||
|
RealStart: &realStart,
|
||||||
|
})
|
||||||
|
workflowStartedEmitted = true
|
||||||
|
}
|
||||||
|
|
||||||
conditions := retrieveCondition(wf)
|
conditions := retrieveCondition(wf)
|
||||||
|
|
||||||
// Retrieving the Status for the main node, which is named after the workflow
|
// Retrieving the Status for the main node, which is named after the workflow
|
||||||
@@ -138,9 +171,9 @@ func LogKubernetesArgo(wfName string, execID string, namespace string, watcher w
|
|||||||
wfl.Fatal().Msg("Could not find the " + wfName + " node in \n" + string(bytified))
|
wfl.Fatal().Msg("Could not find the " + wfName + " node in \n" + string(bytified))
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now().UTC()
|
||||||
start, _ := time.Parse(time.RFC3339, node.StartedAt.String())
|
start, _ := time.Parse(time.RFC3339, node.StartedAt.String())
|
||||||
duration := now.Sub(start)
|
duration := now.Sub(start.UTC())
|
||||||
|
|
||||||
newWatcher := ArgoWatch{
|
newWatcher := ArgoWatch{
|
||||||
Name: node.Name,
|
Name: node.Name,
|
||||||
@@ -163,15 +196,57 @@ func LogKubernetesArgo(wfName string, execID string, namespace string, watcher w
|
|||||||
argoWatcher = &newWatcher
|
argoWatcher = &newWatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// I don't think we need to use WaitGroup here, because the loop itself
|
// ── Per-step completion detection ────────────────────────────────────
|
||||||
// acts as blocking process for the main thread, because Argo watch never closes the channel
|
for _, stepNode := range wf.Status.Nodes {
|
||||||
|
if stepNode.Name == wfName {
|
||||||
|
continue // skip the main DAG node
|
||||||
|
}
|
||||||
|
prev := nodePhases[stepNode.Name]
|
||||||
|
nodePhases[stepNode.Name] = stepNode.Phase
|
||||||
|
|
||||||
|
if prev == stepNode.Phase {
|
||||||
|
continue // no change
|
||||||
|
}
|
||||||
|
if !stepNode.Phase.Completed() && !stepNode.Phase.FailedOrError() {
|
||||||
|
continue // not terminal yet
|
||||||
|
}
|
||||||
|
if prev.Completed() || prev.FailedOrError() {
|
||||||
|
continue // already processed
|
||||||
|
}
|
||||||
|
|
||||||
|
bookingID := extractBookingID(stepNode.Name)
|
||||||
|
if bookingID == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
stepState := enum.SUCCESS
|
||||||
|
if stepNode.Phase.FailedOrError() {
|
||||||
|
stepState = enum.FAILURE
|
||||||
|
}
|
||||||
|
realStart := stepNode.StartedAt.Time
|
||||||
|
realEnd := stepNode.FinishedAt.Time
|
||||||
|
if realEnd.IsZero() {
|
||||||
|
realEnd = time.Now().UTC()
|
||||||
|
}
|
||||||
|
emitLifecycleEvent(octools.WORKFLOW_STEP_DONE_EVENT, octools.WorkflowLifecycleEvent{
|
||||||
|
ExecutionID: execID,
|
||||||
|
ExecutionsID: executionsID,
|
||||||
|
BookingID: bookingID,
|
||||||
|
State: stepState.EnumIndex(),
|
||||||
|
RealStart: &realStart,
|
||||||
|
RealEnd: &realEnd,
|
||||||
|
})
|
||||||
|
// Store for the final recap emitted with WORKFLOW_DONE_EVENT.
|
||||||
|
stepResults[bookingID] = stepNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Pod log streaming ────────────────────────────────────────────────
|
||||||
for _, pod := range wf.Status.Nodes {
|
for _, pod := range wf.Status.Nodes {
|
||||||
|
if pod.Type != wfv1.NodeTypePod {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if !slices.Contains(pods, pod.Name) {
|
if !slices.Contains(pods, pod.Name) {
|
||||||
pl := wfl.With().Str("pod", pod.Name).Logger()
|
pl := wfl.With().Str("pod", pod.Name).Logger()
|
||||||
if wfName == pod.Name {
|
|
||||||
pods = append(pods, pod.Name)
|
|
||||||
continue
|
|
||||||
} // One of the node is the Workflow, the others are the pods so don't try to log on the wf name
|
|
||||||
pl.Info().Msg("Found a new pod to log : " + pod.Name)
|
pl.Info().Msg("Found a new pod to log : " + pod.Name)
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go logKubernetesPods(namespace, wfName, pod.Name, pl, &wg)
|
go logKubernetesPods(namespace, wfName, pod.Name, pl, &wg)
|
||||||
@@ -179,27 +254,93 @@ func LogKubernetesArgo(wfName string, execID string, namespace string, watcher w
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop listening to the chan when the Workflow is completed or something bad happened
|
// ── Workflow terminal phase ──────────────────────────────────────────
|
||||||
if node.Phase.Completed() {
|
if node.Phase.Completed() || node.Phase.FailedOrError() {
|
||||||
wfl.Info().Msg(wfName + " worflow completed")
|
if node.Phase.Completed() {
|
||||||
|
wfl.Info().Msg(wfName + " workflow completed")
|
||||||
|
} else {
|
||||||
|
wfl.Error().Msg(wfName + " has failed, please refer to the logs")
|
||||||
|
wfl.Error().Msg(node.Message)
|
||||||
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
wfl.Info().Msg(wfName + " exiting")
|
wfl.Info().Msg(wfName + " exiting")
|
||||||
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.WORKFLOW_EXECUTION), nil).UpdateOne(map[string]interface{}{
|
|
||||||
"state": enum.SUCCESS.EnumIndex(),
|
finalState := enum.SUCCESS
|
||||||
}, execID)
|
if node.Phase.FailedOrError() {
|
||||||
break
|
finalState = enum.FAILURE
|
||||||
}
|
}
|
||||||
if node.Phase.FailedOrError() {
|
realStart := node.StartedAt.Time
|
||||||
wfl.Error().Msg(wfName + "has failed, please refer to the logs")
|
realEnd := node.FinishedAt.Time
|
||||||
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.WORKFLOW_EXECUTION), nil).UpdateOne(map[string]interface{}{
|
if realEnd.IsZero() {
|
||||||
"state": enum.FAILURE.EnumIndex(),
|
realEnd = time.Now().UTC()
|
||||||
}, execID)
|
}
|
||||||
wfl.Error().Msg(node.Message)
|
|
||||||
|
// Build recap from all observed step results.
|
||||||
|
steps := make([]octools.StepMetric, 0, len(stepResults))
|
||||||
|
for bookingID, s := range stepResults {
|
||||||
|
stepState := enum.SUCCESS
|
||||||
|
if s.Phase.FailedOrError() {
|
||||||
|
stepState = enum.FAILURE
|
||||||
|
}
|
||||||
|
start := s.StartedAt.Time
|
||||||
|
end := s.FinishedAt.Time
|
||||||
|
if end.IsZero() {
|
||||||
|
end = realEnd
|
||||||
|
}
|
||||||
|
steps = append(steps, octools.StepMetric{
|
||||||
|
BookingID: bookingID,
|
||||||
|
State: stepState.EnumIndex(),
|
||||||
|
RealStart: &start,
|
||||||
|
RealEnd: &end,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
emitLifecycleEvent(octools.WORKFLOW_DONE_EVENT, octools.WorkflowLifecycleEvent{
|
||||||
|
ExecutionID: execID,
|
||||||
|
ExecutionsID: executionsID,
|
||||||
|
State: finalState.EnumIndex(),
|
||||||
|
RealStart: &realStart,
|
||||||
|
RealEnd: &realEnd,
|
||||||
|
Steps: steps,
|
||||||
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emitLifecycleEvent publishes a WorkflowLifecycleEvent on the given NATS channel.
|
||||||
|
func emitLifecycleEvent(method octools.NATSMethod, evt octools.WorkflowLifecycleEvent) {
|
||||||
|
payload, err := json.Marshal(evt)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
octools.NewNATSCaller().SetNATSPub(method, octools.NATSResponse{
|
||||||
|
FromApp: "oc-monitord",
|
||||||
|
Method: int(method),
|
||||||
|
Payload: payload,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractBookingID extracts the bookingID (UUID, 36 chars) from an Argo node
|
||||||
|
// display name. Argo step nodes are named "{wfName}.{taskName}" where taskName
|
||||||
|
// is "{resource-name}-{bookingID}" as generated by getArgoName in argo_builder.
|
||||||
|
func extractBookingID(nodeName string) string {
|
||||||
|
parts := strings.SplitN(nodeName, ".", 2)
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
taskName := parts[1]
|
||||||
|
if len(taskName) < 36 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
candidate := taskName[len(taskName)-36:]
|
||||||
|
// Validate UUID shape: 8-4-4-4-12 with dashes at positions 8,13,18,23.
|
||||||
|
if candidate[8] == '-' && candidate[13] == '-' && candidate[18] == '-' && candidate[23] == '-' {
|
||||||
|
return candidate
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func retrieveCondition(wf *wfv1.Workflow) (c Conditions) {
|
func retrieveCondition(wf *wfv1.Workflow) (c Conditions) {
|
||||||
for _, cond := range wf.Status.Conditions {
|
for _, cond := range wf.Status.Conditions {
|
||||||
if cond.Type == "PodRunning" {
|
if cond.Type == "PodRunning" {
|
||||||
@@ -209,12 +350,10 @@ func retrieveCondition(wf *wfv1.Workflow) (c Conditions) {
|
|||||||
c.Completed = cond.Status == "True"
|
c.Completed = cond.Status == "True"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function needed to be executed as a go thread
|
// logKubernetesPods streams pod logs to the structured logger.
|
||||||
func logKubernetesPods(executionId string, wfName string, podName string, logger zerolog.Logger, wg *sync.WaitGroup) {
|
func logKubernetesPods(executionId string, wfName string, podName string, logger zerolog.Logger, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
@@ -241,5 +380,4 @@ func logKubernetesPods(executionId string, wfName string, podName string, logger
|
|||||||
jsonified, _ := json.Marshal(podLog)
|
jsonified, _ := json.Marshal(podLog)
|
||||||
logger.Info().Msg(string(jsonified))
|
logger.Info().Msg(string(jsonified))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
67
main.go
67
main.go
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
|
||||||
"cloud.o-forge.io/core/oc-lib/logs"
|
"cloud.o-forge.io/core/oc-lib/config"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/booking"
|
"cloud.o-forge.io/core/oc-lib/models/booking"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/peer"
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
@@ -26,7 +26,6 @@ import (
|
|||||||
|
|
||||||
"github.com/akamensky/argparse"
|
"github.com/akamensky/argparse"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/goraz/onion"
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,19 +41,23 @@ var wf_logger zerolog.Logger
|
|||||||
var parser argparse.Parser
|
var parser argparse.Parser
|
||||||
var workflowName string
|
var workflowName string
|
||||||
|
|
||||||
const defaultConfigFile = "/etc/oc/ocmonitord_conf.json"
|
|
||||||
const localConfigFile = "./conf/local_ocmonitord_conf.json"
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
o := config.GetConfLoader("oc-monitord")
|
||||||
|
|
||||||
os.Setenv("test_service", "true") // Only for service demo, delete before merging on main
|
|
||||||
parser = *argparse.NewParser("oc-monitord", "Launch the execution of a workflow given as a parameter and sends the produced logs to a loki database")
|
parser = *argparse.NewParser("oc-monitord", "Launch the execution of a workflow given as a parameter and sends the produced logs to a loki database")
|
||||||
loadConfig(&parser)
|
loadConfig(&parser)
|
||||||
|
fmt.Println("sqdqs", o.GetStringDefault("MONGO_URL", "mongodb://mongo:27017"))
|
||||||
|
|
||||||
oclib.InitDaemon("oc-monitord")
|
oclib.InitDaemon("oc-monitord")
|
||||||
|
|
||||||
|
// Lance l'abonné NATS centralisé pour les confirmations PB_CONSIDERS.
|
||||||
|
workflow_builder.StartConsidersListener()
|
||||||
|
|
||||||
|
fmt.Println(conf.GetConfig())
|
||||||
|
|
||||||
logger = u.GetLogger()
|
logger = u.GetLogger()
|
||||||
|
|
||||||
logger.Debug().Msg("Loki URL : " + conf.GetConfig().LokiURL)
|
logger.Debug().Msg("Loki URL : " + config.GetConfig().LokiUrl)
|
||||||
logger.Info().Msg("Workflow executed : " + conf.GetConfig().ExecutionID)
|
logger.Info().Msg("Workflow executed : " + conf.GetConfig().ExecutionID)
|
||||||
exec := u.GetExecution(conf.GetConfig().ExecutionID)
|
exec := u.GetExecution(conf.GetConfig().ExecutionID)
|
||||||
if exec == nil {
|
if exec == nil {
|
||||||
@@ -76,7 +79,7 @@ func main() {
|
|||||||
// // create argo
|
// // create argo
|
||||||
new_wf := workflow_builder.WorflowDB{}
|
new_wf := workflow_builder.WorflowDB{}
|
||||||
|
|
||||||
err := new_wf.LoadFrom(conf.GetConfig().WorkflowID, conf.GetConfig().PeerID)
|
err := new_wf.LoadFrom(conf.GetConfig().WorkflowID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Msg("Could not retrieve workflow " + conf.GetConfig().WorkflowID + " from oc-catalog API")
|
logger.Error().Msg("Could not retrieve workflow " + conf.GetConfig().WorkflowID + " from oc-catalog API")
|
||||||
}
|
}
|
||||||
@@ -117,7 +120,7 @@ func main() {
|
|||||||
func executeInside(ns string, execID string, argo_file_path string) {
|
func executeInside(ns string, execID string, argo_file_path string) {
|
||||||
t, err := tools2.NewService(conf.GetConfig().Mode)
|
t, err := tools2.NewService(conf.GetConfig().Mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Msg("Could not create KubernetesTool")
|
logger.Error().Msg("Could not create KubernetesTool : " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,29 +141,16 @@ func executeInside(ns string, execID string, argo_file_path string) {
|
|||||||
}, execID)
|
}, execID)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.LogKubernetesArgo(name, execID, ns, watcher)
|
l.LogKubernetesArgo(name, execID, ns, ns, watcher)
|
||||||
logger.Info().Msg("Finished, exiting...")
|
logger.Info().Msg("Finished, exiting...")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig(parser *argparse.Parser) {
|
func loadConfig(parser *argparse.Parser) {
|
||||||
var o *onion.Onion
|
|
||||||
o = initOnion(o)
|
|
||||||
setConf(parser)
|
|
||||||
|
|
||||||
// if !IsValidUUID(conf.GetConfig().ExecutionID) {
|
|
||||||
// logger.Fatal().Msg("Provided ID is not an UUID")
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
func setConf(parser *argparse.Parser) {
|
|
||||||
url := parser.String("u", "url", &argparse.Options{Required: true, Default: "http://127.0.0.1:3100", Help: "Url to the Loki database logs will be sent to"})
|
|
||||||
mode := parser.String("M", "mode", &argparse.Options{Required: false, Default: "", Help: "Mode of the execution"})
|
mode := parser.String("M", "mode", &argparse.Options{Required: false, Default: "", Help: "Mode of the execution"})
|
||||||
execution := parser.String("e", "execution", &argparse.Options{Required: true, Help: "Execution ID of the workflow to request from oc-catalog API"})
|
execution := parser.String("e", "execution", &argparse.Options{Required: true, Help: "Execution ID of the workflow to request from oc-catalog API"})
|
||||||
peer := parser.String("p", "peer", &argparse.Options{Required: false, Default: "", Help: "Peer ID of the workflow to request from oc-catalog API"})
|
peer := parser.String("p", "peer", &argparse.Options{Required: false, Default: "", Help: "Peer ID of the workflow to request from oc-catalog API"})
|
||||||
mongo := parser.String("m", "mongo", &argparse.Options{Required: true, Default: "mongodb://127.0.0.1:27017", Help: "URL to reach the MongoDB"})
|
|
||||||
db := parser.String("d", "database", &argparse.Options{Required: true, Default: "DC_myDC", Help: "Name of the database to query in MongoDB"})
|
|
||||||
timeout := parser.Int("t", "timeout", &argparse.Options{Required: false, Default: -1, Help: "Timeout for the execution of the workflow"})
|
timeout := parser.Int("t", "timeout", &argparse.Options{Required: false, Default: -1, Help: "Timeout for the execution of the workflow"})
|
||||||
|
|
||||||
ca := parser.String("c", "ca", &argparse.Options{Required: false, Default: "", Help: "CA file for the Kubernetes cluster"})
|
ca := parser.String("c", "ca", &argparse.Options{Required: false, Default: "", Help: "CA file for the Kubernetes cluster"})
|
||||||
@@ -178,9 +168,6 @@ func setConf(parser *argparse.Parser) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
conf.GetConfig().Logs = "debug"
|
conf.GetConfig().Logs = "debug"
|
||||||
conf.GetConfig().LokiURL = *url
|
|
||||||
conf.GetConfig().MongoURL = *mongo
|
|
||||||
conf.GetConfig().Database = *db
|
|
||||||
conf.GetConfig().Timeout = *timeout
|
conf.GetConfig().Timeout = *timeout
|
||||||
conf.GetConfig().Mode = *mode
|
conf.GetConfig().Mode = *mode
|
||||||
conf.GetConfig().ExecutionID = *execution
|
conf.GetConfig().ExecutionID = *execution
|
||||||
@@ -205,34 +192,6 @@ func setConf(parser *argparse.Parser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initOnion(o *onion.Onion) *onion.Onion {
|
|
||||||
logger = logs.CreateLogger("oc-monitord")
|
|
||||||
configFile := ""
|
|
||||||
|
|
||||||
l3 := onion.NewEnvLayerPrefix("_", "OCMONITORD")
|
|
||||||
l2, err := onion.NewFileLayer(defaultConfigFile, nil)
|
|
||||||
if err == nil {
|
|
||||||
logger.Info().Msg("Config file found : " + defaultConfigFile)
|
|
||||||
configFile = defaultConfigFile
|
|
||||||
}
|
|
||||||
l1, err := onion.NewFileLayer(localConfigFile, nil)
|
|
||||||
if err == nil {
|
|
||||||
logger.Info().Msg("Local config file found " + localConfigFile + ", overriding default file")
|
|
||||||
configFile = localConfigFile
|
|
||||||
}
|
|
||||||
if configFile == "" {
|
|
||||||
logger.Info().Msg("No config file found, using env")
|
|
||||||
o = onion.New(l3)
|
|
||||||
} else if l1 == nil && l2 == nil {
|
|
||||||
o = onion.New(l1, l2, l3)
|
|
||||||
} else if l1 == nil {
|
|
||||||
o = onion.New(l2, l3)
|
|
||||||
} else if l2 == nil {
|
|
||||||
o = onion.New(l1, l3)
|
|
||||||
}
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsValidUUID(u string) bool {
|
func IsValidUUID(u string) bool {
|
||||||
_, err := uuid.Parse(u)
|
_, err := uuid.Parse(u)
|
||||||
return err == nil
|
return err == nil
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package models
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"oc-monitord/conf"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/config"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/common/models"
|
"cloud.o-forge.io/core/oc-lib/models/common/models"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/resources"
|
"cloud.o-forge.io/core/oc-lib/models/resources"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/resources/native_tools"
|
"cloud.o-forge.io/core/oc-lib/models/resources/native_tools"
|
||||||
@@ -20,10 +20,11 @@ type Parameter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Container struct {
|
type Container struct {
|
||||||
Image string `yaml:"image"`
|
Image string `yaml:"image"`
|
||||||
Command []string `yaml:"command,omitempty,flow"`
|
ImagePullPolicy string `yaml:"imagePullPolicy,omitempty"`
|
||||||
Args []string `yaml:"args,omitempty,flow"`
|
Command []string `yaml:"command,omitempty,flow"`
|
||||||
VolumeMounts []VolumeMount `yaml:"volumeMounts,omitempty"`
|
Args []string `yaml:"args,omitempty,flow"`
|
||||||
|
VolumeMounts []VolumeMount `yaml:"volumeMounts,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) AddVolumeMount(volumeMount VolumeMount, volumes []VolumeMount) []VolumeMount {
|
func (c *Container) AddVolumeMount(volumeMount VolumeMount, volumes []VolumeMount) []VolumeMount {
|
||||||
@@ -45,9 +46,10 @@ func (c *Container) AddVolumeMount(volumeMount VolumeMount, volumes []VolumeMoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VolumeMount struct {
|
type VolumeMount struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
MountPath string `yaml:"mountPath"`
|
MountPath string `yaml:"mountPath"`
|
||||||
Storage *resources.StorageResource `yaml:"-"`
|
Storage *resources.StorageResource `yaml:"-"`
|
||||||
|
IsReparted bool `yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Task struct {
|
type Task struct {
|
||||||
@@ -98,17 +100,18 @@ type InOut struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Template struct {
|
type Template struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
Inputs InOut `yaml:"inputs,omitempty"`
|
Inputs InOut `yaml:"inputs,omitempty"`
|
||||||
Outputs InOut `yaml:"outputs,omitempty"`
|
Outputs InOut `yaml:"outputs,omitempty"`
|
||||||
Container Container `yaml:"container,omitempty"`
|
Container Container `yaml:"container,omitempty"`
|
||||||
Dag *Dag `yaml:"dag,omitempty"`
|
Dag *Dag `yaml:"dag,omitempty"`
|
||||||
Metadata TemplateMetadata `yaml:"metadata,omitempty"`
|
Metadata TemplateMetadata `yaml:"metadata,omitempty"`
|
||||||
Resource ServiceResource `yaml:"resource,omitempty"`
|
Resource ServiceResource `yaml:"resource,omitempty"`
|
||||||
|
NodeSelector map[string]string `yaml:"nodeSelector,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (template *Template) CreateEventContainer(execution *workflow_execution.WorkflowExecution, nt *resources.NativeTool, dag *Dag) {
|
func (template *Template) CreateEventContainer(execution *workflow_execution.WorkflowExecution, nt *resources.NativeTool, dag *Dag) {
|
||||||
container := Container{Image: "natsio/nats-box"}
|
container := Container{Image: "natsio/nats-box", ImagePullPolicy: "IfNotPresent"}
|
||||||
container.Command = []string{"sh", "-c"} // all is bash
|
container.Command = []string{"sh", "-c"} // all is bash
|
||||||
|
|
||||||
var event native_tools.WorkflowEventParams
|
var event native_tools.WorkflowEventParams
|
||||||
@@ -136,7 +139,7 @@ func (template *Template) CreateEventContainer(execution *workflow_execution.Wor
|
|||||||
cmd := exec.Command(
|
cmd := exec.Command(
|
||||||
"nats",
|
"nats",
|
||||||
"pub",
|
"pub",
|
||||||
"--server", conf.GetConfig().NatsURL+":4222",
|
"--server", config.GetConfig().NATSUrl+":4222",
|
||||||
tools.WORKFLOW_EVENT.GenerateKey(),
|
tools.WORKFLOW_EVENT.GenerateKey(),
|
||||||
string(payload),
|
string(payload),
|
||||||
)
|
)
|
||||||
@@ -159,7 +162,7 @@ func (template *Template) CreateContainer(exec *workflow_execution.WorkflowExecu
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
inst := instance.(*resources.ProcessingInstance)
|
inst := instance.(*resources.ProcessingInstance)
|
||||||
container := Container{Image: inst.Access.Container.Image}
|
container := Container{Image: inst.Access.Container.Image, ImagePullPolicy: "IfNotPresent"}
|
||||||
if container.Image == "" {
|
if container.Image == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -198,12 +201,20 @@ func (template *Template) ReplacePerEnv(arg string, envs []models.Param) string
|
|||||||
return arg
|
return arg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the metadata that allow Admiralty to pick up an Argo Workflow that needs to be reparted
|
// AddAdmiraltyAnnotations marque le template pour qu'Admiralty route le pod
|
||||||
// The value of "clustername" is the peerId, which must be replaced by the node name's for this specific execution
|
// vers le cluster virtuel correspondant au peerId.
|
||||||
|
//
|
||||||
|
// - elect: "" déclenche le webhook Admiralty sur le pod créé par Argo.
|
||||||
|
// - nodeSelector cible le virtual node Admiralty dont le label
|
||||||
|
// multicluster.admiralty.io/cluster-name vaut peerId,
|
||||||
|
// ce qui contraint le scheduling au cluster distant.
|
||||||
func (t *Template) AddAdmiraltyAnnotations(peerId string) {
|
func (t *Template) AddAdmiraltyAnnotations(peerId string) {
|
||||||
if t.Metadata.Annotations == nil {
|
if t.Metadata.Annotations == nil {
|
||||||
t.Metadata.Annotations = make(map[string]string)
|
t.Metadata.Annotations = make(map[string]string)
|
||||||
}
|
}
|
||||||
t.Metadata.Annotations["multicluster.admiralty.io/elect"] = ""
|
t.Metadata.Annotations["multicluster.admiralty.io/elect"] = ""
|
||||||
t.Metadata.Annotations["multicluster.admiralty.io/clustername"] = peerId
|
if t.NodeSelector == nil {
|
||||||
|
t.NodeSelector = make(map[string]string)
|
||||||
|
}
|
||||||
|
t.NodeSelector["multicluster.admiralty.io/cluster-name"] = peerId
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ package models
|
|||||||
|
|
||||||
type VolumeClaimTemplate struct {
|
type VolumeClaimTemplate struct {
|
||||||
Metadata struct {
|
Metadata struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
|
Annotations map[string]string `yaml:"annotations,omitempty"`
|
||||||
} `yaml:"metadata"`
|
} `yaml:"metadata"`
|
||||||
Spec VolumeSpec `yaml:"spec"`
|
Spec VolumeSpec `yaml:"spec"`
|
||||||
}
|
}
|
||||||
@@ -15,3 +16,12 @@ type VolumeSpec struct {
|
|||||||
} `yaml:"requests"`
|
} `yaml:"requests"`
|
||||||
} `yaml:"resources"`
|
} `yaml:"resources"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExistingVolume references a pre-provisioned PVC (created by oc-datacenter).
|
||||||
|
// Used in Workflow.Spec.ExistingVolumes (yaml: "volumes") instead of volumeClaimTemplates.
|
||||||
|
type ExistingVolume struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
PersistentVolumeClaim struct {
|
||||||
|
ClaimName string `yaml:"claimName"`
|
||||||
|
} `yaml:"persistentVolumeClaim"`
|
||||||
|
}
|
||||||
|
|||||||
BIN
oc-monitord
BIN
oc-monitord
Binary file not shown.
@@ -21,6 +21,7 @@ var _service = map[string]func() (Tool, error){
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewService(name string) (Tool, error) {
|
func NewService(name string) (Tool, error) {
|
||||||
|
return NewKubernetesTool()
|
||||||
service, ok := _service[name]
|
service, ok := _service[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("service not found")
|
return nil, errors.New("service not found")
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"oc-monitord/conf"
|
"oc-monitord/conf"
|
||||||
"oc-monitord/utils"
|
"oc-monitord/utils"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
|
wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
|
||||||
"github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned"
|
"github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned"
|
||||||
@@ -76,7 +75,7 @@ func (k *KubernetesTools) CreateArgoWorkflow(path string, ns string) (string, er
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", errors.New("decoded object is not a Workflow")
|
return "", errors.New("decoded object is not a Workflow")
|
||||||
}
|
}
|
||||||
|
fmt.Println("NAMESPACE", ns)
|
||||||
// Create the workflow in the "argo" namespace
|
// Create the workflow in the "argo" namespace
|
||||||
createdWf, err := k.VersionedSet.ArgoprojV1alpha1().Workflows(ns).Create(context.TODO(), workflow, metav1.CreateOptions{})
|
createdWf, err := k.VersionedSet.ArgoprojV1alpha1().Workflows(ns).Create(context.TODO(), workflow, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,7 +95,7 @@ func (k *KubernetesTools) CreateAccessSecret(access string, password string, sto
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define the Secret object
|
// Define the Secret object
|
||||||
name := storageId+"-secret-s3"
|
name := storageId + "-secret-s3"
|
||||||
secret := &v1.Secret{
|
secret := &v1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
@@ -116,9 +115,9 @@ func (k *KubernetesTools) CreateAccessSecret(access string, password string, sto
|
|||||||
|
|
||||||
func (k *KubernetesTools) GetS3Secret(storageId string, namespace string) *v1.Secret {
|
func (k *KubernetesTools) GetS3Secret(storageId string, namespace string) *v1.Secret {
|
||||||
|
|
||||||
secret, err := k.Set.CoreV1().Secrets(namespace).Get(context.TODO(), storageId + "-secret-s3", metav1.GetOptions{})
|
secret, err := k.Set.CoreV1().Secrets(namespace).Get(context.TODO(), storageId+"-secret-s3", metav1.GetOptions{})
|
||||||
// Get(context.TODO(),storageId + "-artifact-server", metav1.GetOptions{})
|
// Get(context.TODO(),storageId + "-artifact-server", metav1.GetOptions{})
|
||||||
|
|
||||||
if err != nil && !k8serrors.IsNotFound(err) {
|
if err != nil && !k8serrors.IsNotFound(err) {
|
||||||
l := utils.GetLogger()
|
l := utils.GetLogger()
|
||||||
l.Fatal().Msg("An error happened when retrieving secret in " + namespace + " : " + err.Error())
|
l.Fatal().Msg("An error happened when retrieving secret in " + namespace + " : " + err.Error())
|
||||||
@@ -128,77 +127,83 @@ func (k *KubernetesTools) GetS3Secret(storageId string, namespace string) *v1.Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
return secret
|
return secret
|
||||||
// return secret
|
// return secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *KubernetesTools) GetArgoWatch(executionId string, wfName string) (watch.Interface, error) {
|
||||||
func (k *KubernetesTools) GetArgoWatch(executionId string, wfName string) (watch.Interface, error){
|
options := metav1.ListOptions{FieldSelector: "metadata.name=oc-monitor-" + wfName}
|
||||||
options := metav1.ListOptions{FieldSelector: "metadata.name=oc-monitor-"+wfName}
|
|
||||||
|
|
||||||
watcher, err := k.VersionedSet.ArgoprojV1alpha1().Workflows(executionId).Watch(context.Background(), options)
|
watcher, err := k.VersionedSet.ArgoprojV1alpha1().Workflows(executionId).Watch(context.Background(), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Error executing 'argo watch " + wfName + " -n " + executionId + " with ArgoprojV1alpha1 client")
|
return nil, errors.New("Error executing 'argo watch " + wfName + " -n " + executionId + " with ArgoprojV1alpha1 client")
|
||||||
}
|
}
|
||||||
|
|
||||||
return watcher, nil
|
return watcher, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KubernetesTools) GetPodLogger(ns string, wfName string, nodeName string) (io.ReadCloser, error) {
|
func (k *KubernetesTools) GetPodLogger(ns string, wfName string, nodeName string) (io.ReadCloser, error) {
|
||||||
var targetPod v1.Pod
|
var targetPod v1.Pod
|
||||||
|
|
||||||
|
|
||||||
pods, err := k.Set.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{
|
pods, err := k.Set.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{
|
||||||
LabelSelector: "workflows.argoproj.io/workflow="+wfName,
|
LabelSelector: "workflows.argoproj.io/workflow=" + wfName,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to list pods: " + err.Error())
|
return nil, fmt.Errorf("%s", "failed to list pods: "+err.Error())
|
||||||
}
|
}
|
||||||
if len(pods.Items) == 0 {
|
if len(pods.Items) == 0 {
|
||||||
|
|
||||||
return nil, fmt.Errorf("no pods found with label workflows.argoproj.io/workflow="+ wfName + " no pods found with label workflows.argoproj.io/node-name=" + nodeName + " in namespace " + ns)
|
return nil, fmt.Errorf("%s", "no pods found with label workflows.argoproj.io/workflow="+wfName+" no pods found with label workflows.argoproj.io/node-name="+nodeName+" in namespace "+ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pod := range pods.Items {
|
for _, pod := range pods.Items {
|
||||||
if pod.Annotations["workflows.argoproj.io/node-name"] == nodeName {
|
if pod.Annotations["workflows.argoproj.io/node-name"] == nodeName {
|
||||||
targetPod = pod
|
targetPod = pod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if targetPod.Name == "" {
|
||||||
|
return nil, fmt.Errorf("no pod found matching node-name %s in namespace %s", nodeName, ns)
|
||||||
|
}
|
||||||
|
|
||||||
// k8s API throws an error if we try getting logs while the container are not initialized, so we repeat status check there
|
// k8s API throws an error if we try getting logs while the container are not initialized, so we repeat status check there
|
||||||
k.testPodReady(targetPod, ns)
|
k.testPodReady(targetPod, ns)
|
||||||
|
|
||||||
// When using kubec logs for a pod we see it contacts /api/v1/namespaces/NAMESPACE/pods/oc-monitor-PODNAME/log?container=main so we add this container: main to the call
|
// When using kubec logs for a pod we see it contacts /api/v1/namespaces/NAMESPACE/pods/oc-monitor-PODNAME/log?container=main so we add this container: main to the call
|
||||||
req, err := k.Set.CoreV1().Pods(ns).GetLogs(targetPod.Name, &v1.PodLogOptions{Follow: true, Container: "main"}). Stream(context.Background())
|
req, err := k.Set.CoreV1().Pods(ns).GetLogs(targetPod.Name, &v1.PodLogOptions{Follow: true, Container: "main"}).Stream(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(" Error when trying to get logs for " + targetPod.Name + " : " + err.Error())
|
return nil, fmt.Errorf("%s", " Error when trying to get logs for "+targetPod.Name+" : "+err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KubernetesTools) testPodReady(pod v1.Pod, ns string) {
|
func (k *KubernetesTools) testPodReady(pod v1.Pod, ns string) {
|
||||||
for {
|
wfl := utils.GetWFLogger("")
|
||||||
pod, err := k.Set.CoreV1().Pods(ns).Get(context.Background(), pod.Name, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
watcher, err := k.Set.CoreV1().Pods(ns).Watch(context.Background(), metav1.ListOptions{
|
||||||
wfl := utils.GetWFLogger("")
|
FieldSelector: "metadata.name=" + pod.Name,
|
||||||
wfl.Error().Msg("Error fetching pod: " + err.Error() + "\n")
|
ResourceVersion: pod.ResourceVersion,
|
||||||
break
|
})
|
||||||
|
if err != nil {
|
||||||
|
wfl.Error().Msg("Error watching pod: " + err.Error() + "\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer watcher.Stop()
|
||||||
|
|
||||||
|
for event := range watcher.ResultChan() {
|
||||||
|
p, ok := event.Object.(*v1.Pod)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
// It seems that for remote pods the pod gets the Succeeded status before it has time to display the it is ready to run in .status.conditions,so we added the OR condition
|
||||||
var initialized bool
|
if p.Status.Phase == v1.PodSucceeded {
|
||||||
for _, cond := range pod.Status.Conditions {
|
return
|
||||||
// It seems that for remote pods the pod gets the Succeeded status before it has time to display the it is ready to run in .status.conditions,so we added the OR condition
|
}
|
||||||
if (cond.Type == v1.PodReady && cond.Status == v1.ConditionTrue) || pod.Status.Phase == v1.PodSucceeded {
|
for _, cond := range p.Status.Conditions {
|
||||||
initialized = true
|
if cond.Type == v1.PodReady && cond.Status == v1.ConditionTrue {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if initialized {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(2 * time.Second) // avoid hammering the API
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"oc-monitord/conf"
|
"oc-monitord/conf"
|
||||||
. "oc-monitord/models"
|
. "oc-monitord/models"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
oclib_config "cloud.o-forge.io/core/oc-lib/config"
|
|
||||||
"cloud.o-forge.io/core/oc-lib/logs"
|
"cloud.o-forge.io/core/oc-lib/logs"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/peer"
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
@@ -24,7 +24,6 @@ import (
|
|||||||
"cloud.o-forge.io/core/oc-lib/models/workflow/graph"
|
"cloud.o-forge.io/core/oc-lib/models/workflow/graph"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/workflow_execution"
|
"cloud.o-forge.io/core/oc-lib/models/workflow_execution"
|
||||||
"cloud.o-forge.io/core/oc-lib/tools"
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
"github.com/nats-io/nats.go"
|
|
||||||
"github.com/nwtgck/go-fakelish"
|
"github.com/nwtgck/go-fakelish"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -48,6 +47,12 @@ type ArgoBuilder struct {
|
|||||||
Timeout int
|
Timeout int
|
||||||
// RemotePeers contient les IDs des peers distants détectés via Admiralty.
|
// RemotePeers contient les IDs des peers distants détectés via Admiralty.
|
||||||
RemotePeers []string
|
RemotePeers []string
|
||||||
|
// HasLocalCompute indique qu'au moins un processing s'exécute sur le kube local.
|
||||||
|
// Le kube local doit recevoir son propre ArgoKubeEvent COMPUTE_RESOURCE.
|
||||||
|
HasLocalCompute bool
|
||||||
|
// PeerImages associe chaque peer aux images de conteneurs qu'il doit exécuter.
|
||||||
|
// Clé "" désigne le peer local. Utilisé pour le pre-pull et le release post-exec.
|
||||||
|
PeerImages map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workflow est la structure racine du fichier YAML Argo Workflow.
|
// Workflow est la structure racine du fichier YAML Argo Workflow.
|
||||||
@@ -73,16 +78,25 @@ func (b *Workflow) getDag() *Dag {
|
|||||||
return b.Spec.Templates[len(b.Spec.Templates)-1].Dag
|
return b.Spec.Templates[len(b.Spec.Templates)-1].Dag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PodSecurityContext mirrors the subset of k8s PodSecurityContext used by Argo.
|
||||||
|
type PodSecurityContext struct {
|
||||||
|
RunAsUser *int64 `yaml:"runAsUser,omitempty"`
|
||||||
|
RunAsGroup *int64 `yaml:"runAsGroup,omitempty"`
|
||||||
|
FSGroup *int64 `yaml:"fsGroup,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Spec contient la spécification complète du workflow Argo :
|
// Spec contient la spécification complète du workflow Argo :
|
||||||
// compte de service, point d'entrée, volumes, templates et timeout.
|
// compte de service, point d'entrée, volumes, templates et timeout.
|
||||||
type Spec struct {
|
type Spec struct {
|
||||||
ArtifactRepositoryRef
|
ArtifactRepositoryRef
|
||||||
ServiceAccountName string `yaml:"serviceAccountName,omitempty"`
|
ServiceAccountName string `yaml:"serviceAccountName,omitempty"`
|
||||||
Entrypoint string `yaml:"entrypoint"`
|
Entrypoint string `yaml:"entrypoint"`
|
||||||
Arguments []Parameter `yaml:"arguments,omitempty"`
|
Arguments []Parameter `yaml:"arguments,omitempty"`
|
||||||
Volumes []VolumeClaimTemplate `yaml:"volumeClaimTemplates,omitempty"`
|
Volumes []VolumeClaimTemplate `yaml:"volumeClaimTemplates,omitempty"`
|
||||||
Templates []Template `yaml:"templates"`
|
ExistingVolumes []ExistingVolume `yaml:"volumes,omitempty"`
|
||||||
Timeout int `yaml:"activeDeadlineSeconds,omitempty"`
|
Templates []Template `yaml:"templates"`
|
||||||
|
Timeout int `yaml:"activeDeadlineSeconds,omitempty"`
|
||||||
|
SecurityContext *PodSecurityContext `yaml:"securityContext,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDAG est le point d'entrée de la construction du DAG Argo.
|
// CreateDAG est le point d'entrée de la construction du DAG Argo.
|
||||||
@@ -100,7 +114,10 @@ func (b *ArgoBuilder) CreateDAG(exec *workflow_execution.WorkflowExecution, name
|
|||||||
logger = logs.GetLogger()
|
logger = logs.GetLogger()
|
||||||
logger.Info().Msg(fmt.Sprint("Creating DAG ", b.OriginWorkflow.Graph.Items))
|
logger.Info().Msg(fmt.Sprint("Creating DAG ", b.OriginWorkflow.Graph.Items))
|
||||||
// Crée un template Argo pour chaque nœud du graphe et collecte les volumes.
|
// Crée un template Argo pour chaque nœud du graphe et collecte les volumes.
|
||||||
firstItems, lastItems, volumes := b.createTemplates(exec, namespace)
|
firstItems, lastItems, volumes, err := b.createTemplates(exec, namespace)
|
||||||
|
if err != nil {
|
||||||
|
return 0, firstItems, lastItems, err
|
||||||
|
}
|
||||||
b.createVolumes(exec, volumes)
|
b.createVolumes(exec, volumes)
|
||||||
|
|
||||||
if b.Timeout > 0 {
|
if b.Timeout > 0 {
|
||||||
@@ -122,7 +139,7 @@ func (b *ArgoBuilder) CreateDAG(exec *workflow_execution.WorkflowExecution, name
|
|||||||
// Elle gère également le recâblage des dépendances DAG entre sous-workflows
|
// Elle gère également le recâblage des dépendances DAG entre sous-workflows
|
||||||
// imbriqués, et l'ajout du pod de service si nécessaire.
|
// imbriqués, et l'ajout du pod de service si nécessaire.
|
||||||
// Retourne les premières tâches, les dernières tâches et les volumes à créer.
|
// Retourne les premières tâches, les dernières tâches et les volumes à créer.
|
||||||
func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution, namespace string) ([]string, []string, []VolumeMount) {
|
func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution, namespace string) ([]string, []string, []VolumeMount, error) {
|
||||||
volumes := []VolumeMount{}
|
volumes := []VolumeMount{}
|
||||||
firstItems := []string{}
|
firstItems := []string{}
|
||||||
lastItems := []string{}
|
lastItems := []string{}
|
||||||
@@ -138,11 +155,18 @@ func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution
|
|||||||
logger.Info().Msg(fmt.Sprint("Creating template for", item.Processing.GetName(), instance))
|
logger.Info().Msg(fmt.Sprint("Creating template for", item.Processing.GetName(), instance))
|
||||||
if instance == nil || instance.(*resources.ProcessingInstance).Access == nil && instance.(*resources.ProcessingInstance).Access.Container != nil {
|
if instance == nil || instance.(*resources.ProcessingInstance).Access == nil && instance.(*resources.ProcessingInstance).Access.Container != nil {
|
||||||
logger.Error().Msg("Not enough configuration setup, template can't be created : " + item.Processing.GetName())
|
logger.Error().Msg("Not enough configuration setup, template can't be created : " + item.Processing.GetName())
|
||||||
return firstItems, lastItems, volumes
|
return firstItems, lastItems, volumes, nil
|
||||||
|
}
|
||||||
|
// Un même processing peut être bookié sur plusieurs peers : on crée
|
||||||
|
// un template Argo distinct par peer, déployés en parallèle.
|
||||||
|
for _, pb := range getAllPeersForItem(exec, item.ID) {
|
||||||
|
var err error
|
||||||
|
volumes, firstItems, lastItems, err = b.createArgoTemplates(exec,
|
||||||
|
namespace, item.ID, pb.PeerID, pb.BookingID, item.Processing, volumes, firstItems, lastItems)
|
||||||
|
if err != nil {
|
||||||
|
return firstItems, lastItems, volumes, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
volumes, firstItems, lastItems = b.createArgoTemplates(exec,
|
|
||||||
namespace,
|
|
||||||
item.ID, item.Processing, volumes, firstItems, lastItems)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Native Tools de type WORKFLOW_EVENT uniquement ---
|
// --- Native Tools de type WORKFLOW_EVENT uniquement ---
|
||||||
@@ -157,8 +181,12 @@ func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution
|
|||||||
}
|
}
|
||||||
instance := item.NativeTool.GetSelectedInstance(&index)
|
instance := item.NativeTool.GetSelectedInstance(&index)
|
||||||
logger.Info().Msg(fmt.Sprint("Creating template for", item.NativeTool.GetName(), instance))
|
logger.Info().Msg(fmt.Sprint("Creating template for", item.NativeTool.GetName(), instance))
|
||||||
volumes, firstItems, lastItems = b.createArgoTemplates(exec,
|
var err error
|
||||||
namespace, item.ID, item.NativeTool, volumes, firstItems, lastItems)
|
volumes, firstItems, lastItems, err = b.createArgoTemplates(exec,
|
||||||
|
namespace, item.ID, "", item.ID, item.NativeTool, volumes, firstItems, lastItems)
|
||||||
|
if err != nil {
|
||||||
|
return firstItems, lastItems, volumes, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Sous-workflows : chargement, construction récursive et fusion du DAG ---
|
// --- Sous-workflows : chargement, construction récursive et fusion du DAG ---
|
||||||
@@ -178,7 +206,7 @@ func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
firstWfTasks[wf] = fi
|
firstWfTasks[wf] = fi
|
||||||
if ok, depsOfIds := subBuilder.isArgoDependancy(wf); ok { // le sous-workflow est une dépendance d'autre chose
|
if ok, depsOfIds := subBuilder.isArgoDependancy(exec, wf); ok { // le sous-workflow est une dépendance d'autre chose
|
||||||
latestWfTasks[wf] = li
|
latestWfTasks[wf] = li
|
||||||
relatedWfTasks[wf] = depsOfIds
|
relatedWfTasks[wf] = depsOfIds
|
||||||
}
|
}
|
||||||
@@ -217,7 +245,7 @@ func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution
|
|||||||
// Les premières tâches du sous-workflow héritent des dépendances
|
// Les premières tâches du sous-workflow héritent des dépendances
|
||||||
// que le sous-workflow avait vis-à-vis du DAG principal.
|
// que le sous-workflow avait vis-à-vis du DAG principal.
|
||||||
for wfID, fi := range firstWfTasks {
|
for wfID, fi := range firstWfTasks {
|
||||||
deps := b.getArgoDependencies(wfID)
|
deps := b.getArgoDependencies(exec, wfID)
|
||||||
if len(deps) > 0 {
|
if len(deps) > 0 {
|
||||||
for _, dep := range fi {
|
for _, dep := range fi {
|
||||||
for _, task := range b.Workflow.getDag().Tasks {
|
for _, task := range b.Workflow.getDag().Tasks {
|
||||||
@@ -235,53 +263,67 @@ func (b *ArgoBuilder) createTemplates(exec *workflow_execution.WorkflowExecution
|
|||||||
dag.Tasks = append(dag.Tasks, Task{Name: "workflow-service-pod", Template: "workflow-service-pod"})
|
dag.Tasks = append(dag.Tasks, Task{Name: "workflow-service-pod", Template: "workflow-service-pod"})
|
||||||
b.addServiceToArgo()
|
b.addServiceToArgo()
|
||||||
}
|
}
|
||||||
return firstItems, lastItems, volumes
|
return firstItems, lastItems, volumes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createArgoTemplates crée le template Argo pour un nœud du graphe (processing
|
// createArgoTemplates crée le template Argo pour un nœud du graphe (processing
|
||||||
// ou native tool). Il :
|
// ou native tool) sur un peer donné. Il :
|
||||||
// 1. Ajoute la tâche au DAG avec ses dépendances.
|
// 1. Ajoute la tâche au DAG avec ses dépendances.
|
||||||
// 2. Crée le template de container (ou d'événement pour les native tools).
|
// 2. Crée le template de container (ou d'événement pour les native tools).
|
||||||
// 3. Ajoute les annotations Admiralty si le processing est hébergé sur un peer distant.
|
// 3. Ajoute les annotations Admiralty si peerID désigne un peer distant.
|
||||||
// 4. Crée un service Kubernetes si le processing est déclaré IsService.
|
// 4. Crée un service Kubernetes si le processing est déclaré IsService.
|
||||||
// 5. Configure les annotations de stockage (S3, volumes locaux).
|
// 5. Configure les annotations de stockage (S3, volumes locaux).
|
||||||
func (b *ArgoBuilder) createArgoTemplates(
|
func (b *ArgoBuilder) createArgoTemplates(
|
||||||
exec *workflow_execution.WorkflowExecution,
|
exec *workflow_execution.WorkflowExecution,
|
||||||
namespace string,
|
namespace string,
|
||||||
id string,
|
graphID string,
|
||||||
|
peerID string,
|
||||||
|
bookingID string,
|
||||||
obj resources.ResourceInterface,
|
obj resources.ResourceInterface,
|
||||||
volumes []VolumeMount,
|
volumes []VolumeMount,
|
||||||
firstItems []string,
|
firstItems []string,
|
||||||
lastItems []string) ([]VolumeMount, []string, []string) {
|
lastItems []string,
|
||||||
|
) ([]VolumeMount, []string, []string, error) {
|
||||||
|
|
||||||
_, firstItems, lastItems = b.addTaskToArgo(exec, b.Workflow.getDag(), id, obj, firstItems, lastItems)
|
_, firstItems, lastItems = b.addTaskToArgo(exec, b.Workflow.getDag(), graphID, bookingID, obj, firstItems, lastItems)
|
||||||
template := &Template{Name: getArgoName(obj.GetName(), id)}
|
template := &Template{Name: getArgoName(obj.GetName(), bookingID)}
|
||||||
logger.Info().Msg(fmt.Sprint("Creating template for", template.Name))
|
logger.Info().Msg(fmt.Sprint("Creating template for", template.Name))
|
||||||
// Vérifie si le processing est sur un peer distant (Admiralty).
|
|
||||||
isReparted, peer := b.isReparted(obj, id)
|
|
||||||
if obj.GetType() == tools.PROCESSING_RESOURCE.String() {
|
if obj.GetType() == tools.PROCESSING_RESOURCE.String() {
|
||||||
template.CreateContainer(exec, obj.(*resources.ProcessingResource), b.Workflow.getDag())
|
template.CreateContainer(exec, obj.(*resources.ProcessingResource), b.Workflow.getDag())
|
||||||
} else if obj.GetType() == tools.NATIVE_TOOL.String() {
|
} else if obj.GetType() == tools.NATIVE_TOOL.String() {
|
||||||
template.CreateEventContainer(exec, obj.(*resources.NativeTool), b.Workflow.getDag())
|
template.CreateEventContainer(exec, obj.(*resources.NativeTool), b.Workflow.getDag())
|
||||||
}
|
}
|
||||||
|
// Enregistre l'image pour le pre-pull sur le peer cible.
|
||||||
|
// peerID == "" désigne le peer local (clé "" dans PeerImages).
|
||||||
|
b.addPeerImage(peerID, template.Container.Image)
|
||||||
|
|
||||||
|
// Vérifie si le peer est distant (Admiralty).
|
||||||
|
isReparted, remotePeer := b.isPeerReparted(peerID)
|
||||||
if isReparted {
|
if isReparted {
|
||||||
logger.Debug().Msg("Reparted processing, on " + peer.GetID())
|
logger.Debug().Msg("Reparted processing, on " + remotePeer.GetID())
|
||||||
b.RemotePeers = append(b.RemotePeers, peer.GetID())
|
b.RemotePeers = append(b.RemotePeers, remotePeer.GetID())
|
||||||
template.AddAdmiraltyAnnotations(peer.GetID())
|
template.AddAdmiraltyAnnotations(remotePeer.GetID())
|
||||||
|
} else {
|
||||||
|
// Processing local : le kube local doit aussi être configuré.
|
||||||
|
b.HasLocalCompute = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si le processing expose un service Kubernetes, on l'enregistre et on
|
// Si le processing expose un service Kubernetes, on l'enregistre et on
|
||||||
// applique le label "app" pour que le Service puisse le sélectionner.
|
// applique le label "app" pour que le Service puisse le sélectionner.
|
||||||
if obj.GetType() == tools.PROCESSING_RESOURCE.String() && obj.(*resources.ProcessingResource).IsService {
|
if obj.GetType() == tools.PROCESSING_RESOURCE.String() && obj.(*resources.ProcessingResource).IsService {
|
||||||
b.CreateService(exec, id, obj)
|
b.CreateService(exec, graphID, obj)
|
||||||
template.Metadata.Labels = make(map[string]string)
|
template.Metadata.Labels = make(map[string]string)
|
||||||
template.Metadata.Labels["app"] = "oc-service-" + obj.GetName()
|
template.Metadata.Labels["app"] = "oc-service-" + obj.GetName()
|
||||||
}
|
}
|
||||||
|
|
||||||
volumes = b.addStorageAnnotations(exec, id, template, namespace, volumes)
|
var err error
|
||||||
|
volumes, err = b.addStorageAnnotations(exec, graphID, template, namespace, volumes, isReparted)
|
||||||
|
if err != nil {
|
||||||
|
return volumes, firstItems, lastItems, err
|
||||||
|
}
|
||||||
b.Workflow.Spec.Templates = append(b.Workflow.Spec.Templates, *template)
|
b.Workflow.Spec.Templates = append(b.Workflow.Spec.Templates, *template)
|
||||||
return volumes, firstItems, lastItems
|
return volumes, firstItems, lastItems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addStorageAnnotations parcourt tous les nœuds de stockage liés au processing
|
// addStorageAnnotations parcourt tous les nœuds de stockage liés au processing
|
||||||
@@ -290,7 +332,10 @@ func (b *ArgoBuilder) createArgoTemplates(
|
|||||||
// - Pour les stockages S3 : appelle waitForConsiders (STORAGE_RESOURCE) pour
|
// - Pour les stockages S3 : appelle waitForConsiders (STORAGE_RESOURCE) pour
|
||||||
// attendre la validation PB_CONSIDERS avant de configurer les annotations S3.
|
// attendre la validation PB_CONSIDERS avant de configurer les annotations S3.
|
||||||
// - Pour les volumes locaux : ajoute un VolumeMount dans le container.
|
// - Pour les volumes locaux : ajoute un VolumeMount dans le container.
|
||||||
func (b *ArgoBuilder) addStorageAnnotations(exec *workflow_execution.WorkflowExecution, id string, template *Template, namespace string, volumes []VolumeMount) []VolumeMount {
|
// Si isReparted est true (step Admiralty), le volume local est marqué comme
|
||||||
|
// réparti afin que createVolumes ne génère pas de PVC local-path incompatible
|
||||||
|
// avec les virtual kubelets.
|
||||||
|
func (b *ArgoBuilder) addStorageAnnotations(exec *workflow_execution.WorkflowExecution, id string, template *Template, namespace string, volumes []VolumeMount, isReparted bool) ([]VolumeMount, error) {
|
||||||
// Récupère tous les nœuds de stockage connectés au processing courant.
|
// Récupère tous les nœuds de stockage connectés au processing courant.
|
||||||
related := b.OriginWorkflow.GetByRelatedProcessing(id, b.OriginWorkflow.Graph.IsStorage)
|
related := b.OriginWorkflow.GetByRelatedProcessing(id, b.OriginWorkflow.Graph.IsStorage)
|
||||||
|
|
||||||
@@ -315,14 +360,27 @@ func (b *ArgoBuilder) addStorageAnnotations(exec *workflow_execution.WorkflowExe
|
|||||||
// Pour chaque ressource de compute liée à ce stockage S3,
|
// Pour chaque ressource de compute liée à ce stockage S3,
|
||||||
// on notifie via NATS et on attend la validation PB_CONSIDERS
|
// on notifie via NATS et on attend la validation PB_CONSIDERS
|
||||||
// avec DataType = STORAGE_RESOURCE avant de continuer.
|
// avec DataType = STORAGE_RESOURCE avant de continuer.
|
||||||
for _, r := range b.getStorageRelatedProcessing(storage.GetID()) {
|
// Les goroutines tournent en parallèle ; un timeout sur l'une
|
||||||
waitForConsiders(exec.ExecutionsID, tools.STORAGE_RESOURCE, ArgoKubeEvent{
|
// d'elles est une erreur fatale qui stoppe la suite du build.
|
||||||
|
relatedProcessing := b.getStorageRelatedProcessing(storage.GetID())
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
errCh := make(chan error, len(relatedProcessing))
|
||||||
|
for _, r := range relatedProcessing {
|
||||||
|
wg.Add(1)
|
||||||
|
go waitForConsiders(exec.ExecutionsID, tools.STORAGE_RESOURCE, ArgoKubeEvent{
|
||||||
ExecutionsID: exec.ExecutionsID,
|
ExecutionsID: exec.ExecutionsID,
|
||||||
DestPeerID: r.GetID(),
|
DestPeerID: r.GetID(),
|
||||||
Type: tools.STORAGE_RESOURCE,
|
Type: tools.STORAGE_RESOURCE,
|
||||||
SourcePeerID: storage.GetCreatorID(),
|
SourcePeerID: storage.GetCreatorID(),
|
||||||
OriginID: conf.GetConfig().PeerID,
|
OriginID: conf.GetConfig().PeerID,
|
||||||
})
|
}, &wg, errCh)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
close(errCh)
|
||||||
|
for err := range errCh {
|
||||||
|
if err != nil {
|
||||||
|
return volumes, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Configure la référence au dépôt d'artefacts S3 dans le Spec.
|
// Configure la référence au dépôt d'artefacts S3 dans le Spec.
|
||||||
b.addS3annotations(storage, namespace)
|
b.addS3annotations(storage, namespace)
|
||||||
@@ -336,21 +394,43 @@ func (b *ArgoBuilder) addStorageAnnotations(exec *workflow_execution.WorkflowExe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si l'instance de stockage est locale, on monte un volume persistant.
|
// Si l'instance de stockage est locale, on pré-provisionne le PVC via
|
||||||
|
// oc-datacenter (même pattern que MinIO) puis on monte un volume existant.
|
||||||
index := 0
|
index := 0
|
||||||
if s, ok := exec.SelectedInstances[storage.GetID()]; ok {
|
if s, ok := exec.SelectedInstances[storage.GetID()]; ok {
|
||||||
index = s
|
index = s
|
||||||
}
|
}
|
||||||
s := storage.Instances[index]
|
s := storage.Instances[index]
|
||||||
if s.Local {
|
if s.Local {
|
||||||
|
var pvcWg sync.WaitGroup
|
||||||
|
pvcErrCh := make(chan error, 1)
|
||||||
|
pvcWg.Add(1)
|
||||||
|
go waitForConsiders(exec.ExecutionsID, tools.STORAGE_RESOURCE, ArgoKubeEvent{
|
||||||
|
ExecutionsID: exec.ExecutionsID,
|
||||||
|
Type: tools.STORAGE_RESOURCE,
|
||||||
|
SourcePeerID: conf.GetConfig().PeerID,
|
||||||
|
DestPeerID: conf.GetConfig().PeerID,
|
||||||
|
OriginID: conf.GetConfig().PeerID,
|
||||||
|
MinioID: storage.GetID(),
|
||||||
|
Local: true,
|
||||||
|
StorageName: storage.GetName(),
|
||||||
|
}, &pvcWg, pvcErrCh)
|
||||||
|
pvcWg.Wait()
|
||||||
|
close(pvcErrCh)
|
||||||
|
for err := range pvcErrCh {
|
||||||
|
if err != nil {
|
||||||
|
return volumes, err
|
||||||
|
}
|
||||||
|
}
|
||||||
volumes = template.Container.AddVolumeMount(VolumeMount{
|
volumes = template.Container.AddVolumeMount(VolumeMount{
|
||||||
Name: strings.ReplaceAll(strings.ToLower(storage.GetName()), " ", "-"),
|
Name: strings.ReplaceAll(strings.ToLower(storage.GetName()), " ", "-"),
|
||||||
MountPath: s.Source,
|
MountPath: s.Source,
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
|
IsReparted: isReparted,
|
||||||
}, volumes)
|
}, volumes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return volumes
|
return volumes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getStorageRelatedProcessing retourne la liste des ressources de compute
|
// getStorageRelatedProcessing retourne la liste des ressources de compute
|
||||||
@@ -408,10 +488,11 @@ func (b *ArgoBuilder) addS3annotations(storage *resources.StorageResource, names
|
|||||||
// Elle résout les dépendances DAG, propage les paramètres d'environnement,
|
// Elle résout les dépendances DAG, propage les paramètres d'environnement,
|
||||||
// d'entrée et de sortie de l'instance sélectionnée, et met à jour les listes
|
// d'entrée et de sortie de l'instance sélectionnée, et met à jour les listes
|
||||||
// firstItems / lastItems utilisées pour le recâblage des sous-workflows.
|
// firstItems / lastItems utilisées pour le recâblage des sous-workflows.
|
||||||
func (b *ArgoBuilder) addTaskToArgo(exec *workflow_execution.WorkflowExecution, dag *Dag, graphItemID string, processing resources.ResourceInterface,
|
// bookingID est le nom unique de cette instance (peut varier par peer).
|
||||||
|
func (b *ArgoBuilder) addTaskToArgo(exec *workflow_execution.WorkflowExecution, dag *Dag, graphItemID string, bookingID string, processing resources.ResourceInterface,
|
||||||
firstItems []string, lastItems []string) (*Dag, []string, []string) {
|
firstItems []string, lastItems []string) (*Dag, []string, []string) {
|
||||||
|
|
||||||
unique_name := getArgoName(processing.GetName(), graphItemID)
|
unique_name := getArgoName(processing.GetName(), bookingID)
|
||||||
step := Task{Name: unique_name, Template: unique_name}
|
step := Task{Name: unique_name, Template: unique_name}
|
||||||
|
|
||||||
index := 0
|
index := 0
|
||||||
@@ -442,7 +523,7 @@ func (b *ArgoBuilder) addTaskToArgo(exec *workflow_execution.WorkflowExecution,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
step.Dependencies = b.getArgoDependencies(graphItemID)
|
step.Dependencies = b.getArgoDependencies(exec, graphItemID)
|
||||||
|
|
||||||
// Détermine si ce nœud est une première ou une dernière tâche du DAG.
|
// Détermine si ce nœud est une première ou une dernière tâche du DAG.
|
||||||
name := ""
|
name := ""
|
||||||
@@ -453,31 +534,43 @@ func (b *ArgoBuilder) addTaskToArgo(exec *workflow_execution.WorkflowExecution,
|
|||||||
name = b.OriginWorkflow.Graph.Items[graphItemID].Workflow.GetName()
|
name = b.OriginWorkflow.Graph.Items[graphItemID].Workflow.GetName()
|
||||||
}
|
}
|
||||||
if len(step.Dependencies) == 0 && name != "" {
|
if len(step.Dependencies) == 0 && name != "" {
|
||||||
firstItems = append(firstItems, getArgoName(name, graphItemID))
|
firstItems = append(firstItems, getArgoName(name, bookingID))
|
||||||
}
|
}
|
||||||
if ok, _ := b.isArgoDependancy(graphItemID); !ok && name != "" {
|
if ok, _ := b.isArgoDependancy(exec, graphItemID); !ok && name != "" {
|
||||||
lastItems = append(lastItems, getArgoName(name, graphItemID))
|
lastItems = append(lastItems, getArgoName(name, bookingID))
|
||||||
}
|
}
|
||||||
|
|
||||||
dag.Tasks = append(dag.Tasks, step)
|
dag.Tasks = append(dag.Tasks, step)
|
||||||
return dag, firstItems, lastItems
|
return dag, firstItems, lastItems
|
||||||
}
|
}
|
||||||
|
|
||||||
// createVolumes crée les PersistentVolumeClaims Argo (volumeClaimTemplates)
|
// createVolumes référence les PVCs pré-provisionnés par oc-datacenter comme
|
||||||
// pour chaque volume local référencé dans les templates de processing.
|
// volumes existants (ExistingVolumes) dans le Spec Argo.
|
||||||
// TODO: gérer les volumes distants.
|
// Le nom du PVC est calculé de manière déterministe : <storageName>-<executionsID>,
|
||||||
|
// identique à ClaimName() dans oc-datacenter/infrastructure/storage/pvc_setter.go.
|
||||||
func (b *ArgoBuilder) createVolumes(exec *workflow_execution.WorkflowExecution, volumes []VolumeMount) {
|
func (b *ArgoBuilder) createVolumes(exec *workflow_execution.WorkflowExecution, volumes []VolumeMount) {
|
||||||
|
seen := make(map[string]struct{})
|
||||||
for _, volume := range volumes {
|
for _, volume := range volumes {
|
||||||
index := 0
|
name := strings.ReplaceAll(strings.ToLower(volume.Name), " ", "-")
|
||||||
if s, ok := exec.SelectedInstances[volume.Storage.GetID()]; ok {
|
if _, ok := seen[name]; ok {
|
||||||
index = s
|
continue
|
||||||
|
}
|
||||||
|
seen[name] = struct{}{}
|
||||||
|
claimName := name + "-" + exec.ExecutionsID
|
||||||
|
ev := ExistingVolume{}
|
||||||
|
ev.Name = name
|
||||||
|
ev.PersistentVolumeClaim.ClaimName = claimName
|
||||||
|
b.Workflow.Spec.ExistingVolumes = append(b.Workflow.Spec.ExistingVolumes, ev)
|
||||||
|
}
|
||||||
|
// hostPath PVs are created as root:root 0755. Ensure pods can read/write
|
||||||
|
// by running as root when local volumes are present.
|
||||||
|
if len(b.Workflow.Spec.ExistingVolumes) > 0 && b.Workflow.Spec.SecurityContext == nil {
|
||||||
|
zero := int64(0)
|
||||||
|
b.Workflow.Spec.SecurityContext = &PodSecurityContext{
|
||||||
|
RunAsUser: &zero,
|
||||||
|
RunAsGroup: &zero,
|
||||||
|
FSGroup: &zero,
|
||||||
}
|
}
|
||||||
storage := volume.Storage.Instances[index]
|
|
||||||
new_volume := VolumeClaimTemplate{}
|
|
||||||
new_volume.Metadata.Name = strings.ReplaceAll(strings.ToLower(volume.Name), " ", "-")
|
|
||||||
new_volume.Spec.AccessModes = []string{"ReadWriteOnce"}
|
|
||||||
new_volume.Spec.Resources.Requests.Storage = fmt.Sprintf("%v", storage.SizeGB) + storage.SizeType.ToArgo()
|
|
||||||
b.Workflow.Spec.Volumes = append(b.Workflow.Spec.Volumes, new_volume)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,7 +578,7 @@ func (b *ArgoBuilder) createVolumes(exec *workflow_execution.WorkflowExecution,
|
|||||||
// d'au moins un autre nœud du DAG (i.e. s'il existe un lien sortant vers
|
// d'au moins un autre nœud du DAG (i.e. s'il existe un lien sortant vers
|
||||||
// un processing ou un workflow).
|
// un processing ou un workflow).
|
||||||
// Retourne true + la liste des noms Argo des nœuds qui en dépendent.
|
// Retourne true + la liste des noms Argo des nœuds qui en dépendent.
|
||||||
func (b *ArgoBuilder) isArgoDependancy(id string) (bool, []string) {
|
func (b *ArgoBuilder) isArgoDependancy(exec *workflow_execution.WorkflowExecution, id string) (bool, []string) {
|
||||||
dependancyOfIDs := []string{}
|
dependancyOfIDs := []string{}
|
||||||
isDeps := false
|
isDeps := false
|
||||||
for _, link := range b.OriginWorkflow.Graph.Links {
|
for _, link := range b.OriginWorkflow.Graph.Links {
|
||||||
@@ -496,12 +589,16 @@ func (b *ArgoBuilder) isArgoDependancy(id string) (bool, []string) {
|
|||||||
source := b.OriginWorkflow.Graph.Items[link.Destination.ID].Processing
|
source := b.OriginWorkflow.Graph.Items[link.Destination.ID].Processing
|
||||||
if id == link.Source.ID && source != nil {
|
if id == link.Source.ID && source != nil {
|
||||||
isDeps = true
|
isDeps = true
|
||||||
dependancyOfIDs = append(dependancyOfIDs, getArgoName(source.GetName(), link.Destination.ID))
|
for _, pb := range getAllPeersForItem(exec, link.Destination.ID) {
|
||||||
|
dependancyOfIDs = append(dependancyOfIDs, getArgoName(source.GetName(), pb.BookingID))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wourceWF := b.OriginWorkflow.Graph.Items[link.Destination.ID].Workflow
|
wourceWF := b.OriginWorkflow.Graph.Items[link.Destination.ID].Workflow
|
||||||
if id == link.Source.ID && wourceWF != nil {
|
if id == link.Source.ID && wourceWF != nil {
|
||||||
isDeps = true
|
isDeps = true
|
||||||
dependancyOfIDs = append(dependancyOfIDs, getArgoName(wourceWF.GetName(), link.Destination.ID))
|
for _, pb := range getAllPeersForItem(exec, link.Destination.ID) {
|
||||||
|
dependancyOfIDs = append(dependancyOfIDs, getArgoName(wourceWF.GetName(), pb.BookingID))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isDeps, dependancyOfIDs
|
return isDeps, dependancyOfIDs
|
||||||
@@ -509,7 +606,9 @@ func (b *ArgoBuilder) isArgoDependancy(id string) (bool, []string) {
|
|||||||
|
|
||||||
// getArgoDependencies retourne la liste des noms de tâches Argo dont dépend
|
// getArgoDependencies retourne la liste des noms de tâches Argo dont dépend
|
||||||
// le nœud identifié par id (liens entrants depuis des processings).
|
// le nœud identifié par id (liens entrants depuis des processings).
|
||||||
func (b *ArgoBuilder) getArgoDependencies(id string) (dependencies []string) {
|
// Si le processing source est bookié sur N peers, toutes ses instances sont
|
||||||
|
// retournées comme dépendances (la tâche courante attend toutes les instances).
|
||||||
|
func (b *ArgoBuilder) getArgoDependencies(exec *workflow_execution.WorkflowExecution, id string) (dependencies []string) {
|
||||||
for _, link := range b.OriginWorkflow.Graph.Links {
|
for _, link := range b.OriginWorkflow.Graph.Links {
|
||||||
if _, ok := b.OriginWorkflow.Graph.Items[link.Source.ID]; !ok {
|
if _, ok := b.OriginWorkflow.Graph.Items[link.Source.ID]; !ok {
|
||||||
logger.Info().Msg(fmt.Sprint("Could not find the source of the link", link.Source.ID))
|
logger.Info().Msg(fmt.Sprint("Could not find the source of the link", link.Source.ID))
|
||||||
@@ -517,9 +616,9 @@ func (b *ArgoBuilder) getArgoDependencies(id string) (dependencies []string) {
|
|||||||
}
|
}
|
||||||
source := b.OriginWorkflow.Graph.Items[link.Source.ID].Processing
|
source := b.OriginWorkflow.Graph.Items[link.Source.ID].Processing
|
||||||
if id == link.Destination.ID && source != nil {
|
if id == link.Destination.ID && source != nil {
|
||||||
dependency_name := getArgoName(source.GetName(), link.Source.ID)
|
for _, pb := range getAllPeersForItem(exec, link.Source.ID) {
|
||||||
dependencies = append(dependencies, dependency_name)
|
dependencies = append(dependencies, getArgoName(source.GetName(), pb.BookingID))
|
||||||
continue
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -535,139 +634,93 @@ func getArgoName(raw_name string, component_id string) (formatedName string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// isReparted vérifie si le processing est hébergé sur un Compute appartenant
|
// peerBooking associe un peerID à son bookingID pour un item du graphe.
|
||||||
// à un peer distant (Relation != 1, i.e. pas le peer local).
|
type peerBooking struct {
|
||||||
// Si c'est le cas, elle retourne true et le Peer concerné pour qu'Admiralty
|
PeerID string
|
||||||
// puisse router les pods vers le bon cluster.
|
BookingID string
|
||||||
func (b *ArgoBuilder) isReparted(processing resources.ResourceInterface, graphID string) (bool, *peer.Peer) {
|
}
|
||||||
computeAttached := b.retrieveProcessingCompute(graphID)
|
|
||||||
if computeAttached == nil {
|
// getAllPeersForItem retourne tous les (peerID, bookingID) enregistrés dans
|
||||||
logger.Error().Msg("No compute was found attached to processing " + processing.GetName() + " : " + processing.GetID())
|
// PeerBookByGraph pour un item donné. Si aucun booking n'est trouvé (item
|
||||||
panic(0)
|
// non encore planifié ou sous-workflow), retourne une entrée locale de
|
||||||
|
// fallback avec BookingID = graphItemID.
|
||||||
|
func getAllPeersForItem(exec *workflow_execution.WorkflowExecution, graphItemID string) []peerBooking {
|
||||||
|
var result []peerBooking
|
||||||
|
for peerID, byGraph := range exec.PeerBookByGraph {
|
||||||
|
if bookings, ok := byGraph[graphItemID]; ok && len(bookings) > 0 {
|
||||||
|
result = append(result, peerBooking{PeerID: peerID, BookingID: bookings[0]})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(result) == 0 {
|
||||||
|
result = []peerBooking{{PeerID: "", BookingID: graphItemID}}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// isPeerReparted vérifie si le peerID désigne un peer distant (Relation != 1).
|
||||||
|
// Un peerID vide signifie exécution locale : retourne false sans appel réseau.
|
||||||
|
func (b *ArgoBuilder) isPeerReparted(peerID string) (bool, *peer.Peer) {
|
||||||
|
if peerID == "" {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Résolution du Peer propriétaire du Compute via l'API oc-lib.
|
|
||||||
req := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", nil, nil)
|
req := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", nil, nil)
|
||||||
if req == nil {
|
if req == nil {
|
||||||
fmt.Println("TODO : handle error when trying to create a request on the Peer Collection")
|
fmt.Println("TODO : handle error when trying to create a request on the Peer Collection")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
res := req.LoadOne(computeAttached.CreatorID)
|
res := req.LoadOne(peerID)
|
||||||
if res.Err != "" {
|
if res.Err != "" {
|
||||||
fmt.Print("TODO : handle error when requesting PeerID")
|
fmt.Print("TODO : handle error when requesting PeerID: " + res.Err)
|
||||||
fmt.Print(res.Err)
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
peer := res.ToPeer()
|
p := res.ToPeer()
|
||||||
|
|
||||||
// Relation == 1 signifie "moi-même" : le processing est local.
|
// Relation == 1 signifie "moi-même" : le processing est local.
|
||||||
isNotReparted := peer.Relation == 1
|
isNotReparted := p.Relation == 1
|
||||||
logger.Info().Msg(fmt.Sprint("Result IsMySelf for ", peer.UUID, " : ", isNotReparted))
|
logger.Info().Msg(fmt.Sprint("Result IsMySelf for ", p.UUID, " : ", isNotReparted))
|
||||||
|
return !isNotReparted, p
|
||||||
return !isNotReparted, peer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieveProcessingCompute parcourt les liens du graphe pour retrouver
|
// waitForConsiders publie un ArgoKubeEvent sur NATS puis attend la confirmation
|
||||||
// la ressource de Compute directement connectée au nœud graphID.
|
// PB_CONSIDERS via le cache global (globalConsidersCache), sans ouvrir de
|
||||||
// Retourne nil si aucun Compute n'est trouvé.
|
// connexion NATS supplémentaire. Le listener centralisé (StartConsidersListener)
|
||||||
func (b *ArgoBuilder) retrieveProcessingCompute(graphID string) *resources.ComputeResource {
|
// dispatche le message vers le bon canal.
|
||||||
for _, link := range b.OriginWorkflow.Graph.Links {
|
|
||||||
var oppositeId string
|
|
||||||
if link.Source.ID == graphID {
|
|
||||||
oppositeId = link.Destination.ID
|
|
||||||
} else if link.Destination.ID == graphID {
|
|
||||||
oppositeId = link.Source.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
if oppositeId != "" {
|
|
||||||
dt, res := b.OriginWorkflow.Graph.GetResource(oppositeId)
|
|
||||||
if dt == oclib.COMPUTE_RESOURCE {
|
|
||||||
return res.(*resources.ComputeResource)
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// waitForConsiders publie un ArgoKubeEvent sur le canal NATS ARGO_KUBE_EVENT
|
|
||||||
// puis se bloque jusqu'à réception d'un PropalgationMessage vérifiant :
|
|
||||||
// - Action == PB_CONSIDERS
|
|
||||||
// - DataType == dataType (COMPUTE_RESOURCE ou STORAGE_RESOURCE)
|
|
||||||
// - Payload décodé en JSON contenant "executions_id" == executionsId
|
|
||||||
//
|
|
||||||
// Cela garantit que l'infrastructure distante (Admiralty ou Minio) a bien
|
|
||||||
// pris en compte la demande avant que la construction du workflow continue.
|
|
||||||
// Un timeout de 5 minutes est appliqué pour éviter un blocage indéfini.
|
// Un timeout de 5 minutes est appliqué pour éviter un blocage indéfini.
|
||||||
func waitForConsiders(executionsId string, dataType tools.DataType, event ArgoKubeEvent) {
|
func waitForConsiders(executionsId string, dataType tools.DataType, event ArgoKubeEvent, wg *sync.WaitGroup, errCh chan<- error) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
// Sérialise l'événement et le publie sur ARGO_KUBE_EVENT.
|
// Sérialise l'événement et le publie sur ARGO_KUBE_EVENT.
|
||||||
b, err := json.Marshal(event)
|
b, err := json.Marshal(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Msg("Cannot marshal ArgoKubeEvent: " + err.Error())
|
logger.Error().Msg("Cannot marshal ArgoKubeEvent: " + err.Error())
|
||||||
|
errCh <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tools.NewNATSCaller().SetNATSPub(tools.ARGO_KUBE_EVENT, tools.NATSResponse{
|
tools.NewNATSCaller().SetNATSPub(tools.ARGO_KUBE_EVENT, tools.NATSResponse{
|
||||||
FromApp: "oc-monitord",
|
FromApp: "oc-monitord",
|
||||||
Datatype: dataType,
|
Datatype: dataType,
|
||||||
User: "root",
|
User: "root",
|
||||||
Method: int(tools.PROPALGATION_EVENT),
|
Method: int(tools.ARGO_KUBE_EVENT),
|
||||||
Payload: b,
|
Payload: b,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Connexion NATS pour écouter la réponse PB_CONSIDERS.
|
// Enregistrement dans le cache et attente de la confirmation.
|
||||||
natsURL := oclib_config.GetConfig().NATSUrl
|
// Pour COMPUTE_RESOURCE, SourcePeerID différencie le peer compute (local ou distant).
|
||||||
if natsURL == "" {
|
// Pour STORAGE_RESOURCE, SourcePeerID est le peer hébergeant le stockage.
|
||||||
logger.Error().Msg("NATS_SERVER not set, skipping PB_CONSIDERS wait")
|
key := considersKey(executionsId, dataType, event.SourcePeerID)
|
||||||
return
|
ch, unregister := globalConsidersCache.register(key)
|
||||||
}
|
defer unregister()
|
||||||
nc, err := nats.Connect(natsURL)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error().Msg("NATS connect error waiting for PB_CONSIDERS: " + err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer nc.Close()
|
|
||||||
|
|
||||||
// Souscription au canal PROPALGATION_EVENT avec un buffer de 64 messages.
|
select {
|
||||||
ch := make(chan *nats.Msg, 64)
|
case <-ch:
|
||||||
sub, err := nc.ChanSubscribe(tools.PROPALGATION_EVENT.GenerateKey(), ch)
|
logger.Info().Msg(fmt.Sprintf("PB_CONSIDERS received for executions_id=%s datatype=%s source_peer=%s dest_peer=%s", executionsId, dataType.String(), event.SourcePeerID, event.DestPeerID))
|
||||||
if err != nil {
|
errCh <- nil
|
||||||
logger.Error().Msg("NATS subscribe error waiting for PB_CONSIDERS: " + err.Error())
|
case <-time.After(5 * time.Minute):
|
||||||
return
|
err := fmt.Errorf("timeout waiting for PB_CONSIDERS executions_id=%s datatype=%s", executionsId, dataType.String())
|
||||||
}
|
logger.Error().Msg(err.Error())
|
||||||
defer sub.Unsubscribe()
|
errCh <- err
|
||||||
|
|
||||||
timeout := time.After(5 * time.Minute)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case msg := <-ch:
|
|
||||||
// Désérialise le message en PropalgationMessage.
|
|
||||||
var pm tools.PropalgationMessage
|
|
||||||
if err := json.Unmarshal(msg.Data, &pm); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Filtre : action, type de données.
|
|
||||||
if pm.Action != tools.PB_CONSIDERS || pm.DataType != int(dataType) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Filtre : executions_id dans le Payload du PropalgationMessage.
|
|
||||||
var body struct {
|
|
||||||
ExecutionsID string `json:"executions_id"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(pm.Payload, &body); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if body.ExecutionsID != executionsId {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
logger.Info().Msg(fmt.Sprintf("PB_CONSIDERS received for executions_id=%s datatype=%s", executionsId, dataType.String()))
|
|
||||||
return
|
|
||||||
case <-timeout:
|
|
||||||
logger.Warn().Msg(fmt.Sprintf("Timeout waiting for PB_CONSIDERS executions_id=%s datatype=%s", executionsId, dataType.String()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,8 +740,35 @@ type ArgoKubeEvent struct {
|
|||||||
// OriginID est le peer qui a initié la demande de provisionnement ;
|
// OriginID est le peer qui a initié la demande de provisionnement ;
|
||||||
// la réponse PB_CONSIDERS lui sera renvoyée.
|
// la réponse PB_CONSIDERS lui sera renvoyée.
|
||||||
OriginID string `json:"origin_id"`
|
OriginID string `json:"origin_id"`
|
||||||
|
// MinioID est l'ID de la ressource storage (Minio ou local PVC).
|
||||||
|
MinioID string `json:"minio_id,omitempty"`
|
||||||
|
// Local signale un storage Local=true (PVC pré-provisionné par oc-datacenter).
|
||||||
|
Local bool `json:"local,omitempty"`
|
||||||
|
// StorageName est le nom normalisé du storage, utilisé pour calculer le claimName.
|
||||||
|
StorageName string `json:"storage_name,omitempty"`
|
||||||
|
// Images est la liste des images de conteneurs à pre-pull sur le peer cible
|
||||||
|
// avant le démarrage du workflow. Vide pour les events STORAGE_RESOURCE.
|
||||||
|
Images []string `json:"images,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addPeerImage enregistre une image à pre-pull pour un peer donné.
|
||||||
|
// Clé "" désigne le peer local. Les doublons sont ignorés.
|
||||||
|
func (b *ArgoBuilder) addPeerImage(peerID, image string) {
|
||||||
|
if image == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b.PeerImages == nil {
|
||||||
|
b.PeerImages = make(map[string][]string)
|
||||||
|
}
|
||||||
|
for _, existing := range b.PeerImages[peerID] {
|
||||||
|
if existing == image {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.PeerImages[peerID] = append(b.PeerImages[peerID], image)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// CompleteBuild finalise la construction du workflow Argo après la génération
|
// CompleteBuild finalise la construction du workflow Argo après la génération
|
||||||
// du DAG. Elle effectue dans l'ordre :
|
// du DAG. Elle effectue dans l'ordre :
|
||||||
// 1. Pour chaque peer distant (Admiralty) : publie un ArgoKubeEvent de type
|
// 1. Pour chaque peer distant (Admiralty) : publie un ArgoKubeEvent de type
|
||||||
@@ -701,30 +781,68 @@ type ArgoKubeEvent struct {
|
|||||||
func (b *ArgoBuilder) CompleteBuild(executionsId string) (string, error) {
|
func (b *ArgoBuilder) CompleteBuild(executionsId string) (string, error) {
|
||||||
logger.Info().Msg("DEV :: Completing build")
|
logger.Info().Msg("DEV :: Completing build")
|
||||||
|
|
||||||
// --- Étape 1 : validation Admiralty pour chaque peer distant ---
|
// --- Étape 1 : validation kube pour tous les peers (local + distants) ---
|
||||||
for _, peer := range b.RemotePeers {
|
// Les goroutines tournent en parallèle ; un timeout est une erreur fatale.
|
||||||
logger.Info().Msg(fmt.Sprint("DEV :: Launching Admiralty Setup for ", peer))
|
// Déduplique RemotePeers : plusieurs processings peuvent pointer vers le même
|
||||||
// Publie l'événement COMPUTE_RESOURCE et attend PB_CONSIDERS (bloquant).
|
// peer distant, on ne doit envoyer qu'un seul ArgoKubeEvent par peer.
|
||||||
waitForConsiders(executionsId, tools.COMPUTE_RESOURCE, ArgoKubeEvent{
|
seen := make(map[string]struct{})
|
||||||
ExecutionsID: executionsId,
|
uniqueRemotePeers := b.RemotePeers[:0]
|
||||||
Type: tools.COMPUTE_RESOURCE,
|
for _, p := range b.RemotePeers {
|
||||||
DestPeerID: conf.GetConfig().PeerID,
|
if _, ok := seen[p]; !ok {
|
||||||
SourcePeerID: peer,
|
seen[p] = struct{}{}
|
||||||
OriginID: conf.GetConfig().PeerID,
|
uniqueRemotePeers = append(uniqueRemotePeers, p)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
b.RemotePeers = uniqueRemotePeers
|
||||||
|
|
||||||
// --- Étape 2 : mise à jour du nom de cluster Admiralty ---
|
total := len(b.RemotePeers)
|
||||||
// Le nom final du cluster cible est "target-<peerId>-<executionsId>".
|
if b.HasLocalCompute {
|
||||||
for _, template := range b.Workflow.Spec.Templates {
|
total++
|
||||||
if len(template.Metadata.Annotations) > 0 {
|
}
|
||||||
if peerId, ok := template.Metadata.Annotations["multicluster.admiralty.io/clustername"]; ok {
|
var wg sync.WaitGroup
|
||||||
template.Metadata.Annotations["multicluster.admiralty.io/clustername"] = "target-" + tools.GetConcatenatedName(peerId, executionsId)
|
errCh := make(chan error, total)
|
||||||
}
|
|
||||||
|
// Le kube local doit aussi être configuré s'il porte au moins un processing.
|
||||||
|
if b.HasLocalCompute {
|
||||||
|
if localPeer, err := oclib.GetMySelf(); err == nil {
|
||||||
|
logger.Info().Msg("DEV :: Launching local kube setup for " + localPeer.GetID())
|
||||||
|
wg.Add(1)
|
||||||
|
go waitForConsiders(executionsId, tools.COMPUTE_RESOURCE, ArgoKubeEvent{
|
||||||
|
ExecutionsID: executionsId,
|
||||||
|
Type: tools.COMPUTE_RESOURCE,
|
||||||
|
DestPeerID: localPeer.GetID(),
|
||||||
|
SourcePeerID: localPeer.GetID(),
|
||||||
|
OriginID: localPeer.GetID(),
|
||||||
|
Images: b.PeerImages[""], // images à pre-pull sur le cluster local
|
||||||
|
}, &wg, errCh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Étape 3 : génération et écriture du fichier YAML ---
|
// Peers distants via Admiralty.
|
||||||
|
for _, peer := range b.RemotePeers {
|
||||||
|
logger.Info().Msg(fmt.Sprint("DEV :: Launching Admiralty Setup for ", peer))
|
||||||
|
if self, err := oclib.GetMySelf(); err == nil {
|
||||||
|
wg.Add(1)
|
||||||
|
go waitForConsiders(executionsId, tools.COMPUTE_RESOURCE, ArgoKubeEvent{
|
||||||
|
ExecutionsID: executionsId,
|
||||||
|
Type: tools.COMPUTE_RESOURCE,
|
||||||
|
DestPeerID: self.GetID(),
|
||||||
|
SourcePeerID: peer,
|
||||||
|
OriginID: self.GetID(),
|
||||||
|
Images: b.PeerImages[peer], // images à pre-pull sur le cluster distant (via kubeconfig Admiralty)
|
||||||
|
}, &wg, errCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
close(errCh)
|
||||||
|
for err := range errCh {
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Étape 2 : génération et écriture du fichier YAML ---
|
||||||
random_name := fakelish.GenerateFakeWord(5, 8) + "-" + fakelish.GenerateFakeWord(5, 8)
|
random_name := fakelish.GenerateFakeWord(5, 8) + "-" + fakelish.GenerateFakeWord(5, 8)
|
||||||
b.Workflow.Metadata.Name = "oc-monitor-" + random_name
|
b.Workflow.Metadata.Name = "oc-monitor-" + random_name
|
||||||
logger = oclib.GetLogger()
|
logger = oclib.GetLogger()
|
||||||
@@ -734,7 +852,7 @@ func (b *ArgoBuilder) CompleteBuild(executionsId string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
// Nom de fichier horodaté au format DD_MM_YYYY_hhmmss.
|
// Nom de fichier horodaté au format DD_MM_YYYY_hhmmss.
|
||||||
current_timestamp := time.Now().Format("02_01_2006_150405")
|
current_timestamp := time.Now().UTC().Format("02_01_2006_150405")
|
||||||
file_name := random_name + "_" + current_timestamp + ".yml"
|
file_name := random_name + "_" + current_timestamp + ".yml"
|
||||||
workflows_dir := "./argo_workflows/"
|
workflows_dir := "./argo_workflows/"
|
||||||
err = os.WriteFile(workflows_dir+file_name, []byte(yamlified), 0660)
|
err = os.WriteFile(workflows_dir+file_name, []byte(yamlified), 0660)
|
||||||
|
|||||||
100
workflow_builder/considers_cache.go
Normal file
100
workflow_builder/considers_cache.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package workflow_builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"cloud.o-forge.io/core/oc-lib/logs"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
// considersCache stocke les canaux en attente d'un PB_CONSIDERS,
|
||||||
|
// indexés par "executionsId:dataType". Un même message NATS réveille
|
||||||
|
// tous les waiters enregistrés sous la même clé (broadcast).
|
||||||
|
type considersCache struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
pending map[string][]chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalConsidersCache = &considersCache{
|
||||||
|
pending: make(map[string][]chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// considersKey construit la clé du cache à partir de l'ID d'exécution,
|
||||||
|
// du type de données et du peer compute (SourcePeerID).
|
||||||
|
// peerID permet de différencier plusieurs waiters COMPUTE_RESOURCE du même
|
||||||
|
// executionsId (1 local + N distants en parallèle).
|
||||||
|
func considersKey(executionsId string, dataType tools.DataType, peerID string) string {
|
||||||
|
key := executionsId + ":" + strconv.Itoa(dataType.EnumIndex())
|
||||||
|
if peerID != "" {
|
||||||
|
key += ":" + peerID
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
// register inscrit un nouveau canal d'attente pour la clé donnée.
|
||||||
|
// Retourne le canal à lire et une fonction de désinscription à appeler en defer.
|
||||||
|
func (c *considersCache) register(key string) (<-chan struct{}, func()) {
|
||||||
|
ch := make(chan struct{}, 1)
|
||||||
|
c.mu.Lock()
|
||||||
|
c.pending[key] = append(c.pending[key], ch)
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
unregister := func() {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
list := c.pending[key]
|
||||||
|
for i, existing := range list {
|
||||||
|
if existing == ch {
|
||||||
|
c.pending[key] = append(list[:i], list[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(c.pending[key]) == 0 {
|
||||||
|
delete(c.pending, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ch, unregister
|
||||||
|
}
|
||||||
|
|
||||||
|
// confirm réveille tous les waiters enregistrés sous la clé donnée
|
||||||
|
// et les supprime du cache.
|
||||||
|
func (c *considersCache) confirm(key string) {
|
||||||
|
c.mu.Lock()
|
||||||
|
list := c.pending[key]
|
||||||
|
delete(c.pending, key)
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
for _, ch := range list {
|
||||||
|
select {
|
||||||
|
case ch <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartConsidersListener démarre un abonné NATS global via ListenNats (oclib)
|
||||||
|
// qui reçoit les messages CONSIDERS_EVENT et réveille les goroutines en attente
|
||||||
|
// via globalConsidersCache. Doit être appelé une seule fois au démarrage.
|
||||||
|
func StartConsidersListener() {
|
||||||
|
log := logs.GetLogger()
|
||||||
|
log.Info().Msg("Considers NATS listener starting on " + tools.CONSIDERS_EVENT.GenerateKey())
|
||||||
|
go tools.NewNATSCaller().ListenNats(map[tools.NATSMethod]func(tools.NATSResponse){
|
||||||
|
tools.CONSIDERS_EVENT: func(resp tools.NATSResponse) {
|
||||||
|
fmt.Println("CONSIDERS")
|
||||||
|
var body struct {
|
||||||
|
ExecutionsID string `json:"executions_id"`
|
||||||
|
PeerID string `json:"peer_id,omitempty"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(resp.Payload, &body); err != nil {
|
||||||
|
log.Error().Msg("CONSIDERS_EVENT: cannot unmarshal payload: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key := considersKey(body.ExecutionsID, resp.Datatype, body.PeerID)
|
||||||
|
log.Info().Msg(fmt.Sprintf("CONSIDERS_EVENT dispatched for key=%s", key))
|
||||||
|
globalConsidersCache.confirm(key)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -14,20 +14,20 @@ type WorflowDB struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the obj!ects from the mxgraphxml stored in the workflow given as a parameter
|
// Create the obj!ects from the mxgraphxml stored in the workflow given as a parameter
|
||||||
func (w *WorflowDB) LoadFrom(workflow_id string, peerID string) error {
|
func (w *WorflowDB) LoadFrom(workflow_id string) error {
|
||||||
logger.Info().Msg("Loading workflow from " + workflow_id)
|
logger.Info().Msg("Loading workflow from " + workflow_id)
|
||||||
var err error
|
var err error
|
||||||
if w.Workflow, err = w.getWorkflow(workflow_id, peerID); err != nil {
|
if w.Workflow, err = w.getWorkflow(workflow_id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use oclib to retrieve the graph contained in the workflow referenced
|
// Use oclib to retrieve the graph contained in the workflow referenced
|
||||||
func (w *WorflowDB) getWorkflow(workflow_id string, peerID string) (workflow *workflow.Workflow, err error) {
|
func (w *WorflowDB) getWorkflow(workflow_id string) (workflow *workflow.Workflow, err error) {
|
||||||
logger := oclib.GetLogger()
|
logger := oclib.GetLogger()
|
||||||
|
|
||||||
lib_data := oclib.NewRequest(oclib.LibDataEnum(oclib.WORKFLOW), "", peerID, []string{}, nil).LoadOne(workflow_id)
|
lib_data := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.WORKFLOW), nil).LoadOne(workflow_id)
|
||||||
logger.Info().Msg(fmt.Sprint("ERR", lib_data.Code, lib_data.Err))
|
logger.Info().Msg(fmt.Sprint("ERR", lib_data.Code, lib_data.Err))
|
||||||
if lib_data.Code != 200 {
|
if lib_data.Code != 200 {
|
||||||
logger.Error().Msg("Error loading the graph")
|
logger.Error().Msg("Error loading the graph")
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import (
|
|||||||
|
|
||||||
func TestGetGraph(t *testing.T) {
|
func TestGetGraph(t *testing.T) {
|
||||||
w := WorflowDB{}
|
w := WorflowDB{}
|
||||||
w.LoadFrom("test-log", "")
|
w.LoadFrom("test-log")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user